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 // ----------------------------------------------------------------------------
40 #pragma implementation "dcclient.h"
43 #include "wx/dcclient.h"
44 #include "wx/dcmemory.h"
45 #include "wx/window.h"
53 #pragma message disable nosimpint
57 #pragma message enable nosimpint
60 #include "wx/motif/private.h"
63 #include <float.h> // for M_PI
73 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
79 // Fudge factor (VZ: what??)
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
87 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
88 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
95 Drawable src
, Drawable dest
,
98 unsigned int w
, unsigned int h
,
100 bool more
, XImage
**cache
);
102 // ============================================================================
104 // ============================================================================
107 * compare two doubles and return the larger rounded
110 static int roundmax(double a
, double b
)
112 return (int)((a
> b
? a
: b
) + 0.5);
116 * compare two doubles and return the smaller rounded
119 static int roundmin(double a
, double b
)
121 return (int)((a
< b
? a
: b
) - 0.5);
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
129 wxWindowDC::wxWindowDC()
132 m_gcBacking
= (WXGC
) 0;
134 m_backgroundPixel
= -1;
135 m_currentPenWidth
= 1;
136 m_currentPenJoin
= -1;
137 m_currentPenDashCount
= -1;
138 m_currentPenDash
= (wxX11Dash
*) NULL
;
141 // m_currentBkMode = wxTRANSPARENT;
142 m_colour
= wxColourDisplay();
143 m_display
= (WXDisplay
*) NULL
;
144 m_currentRegion
= (WXRegion
) 0;
145 m_userRegion
= (WXRegion
) 0;
146 m_pixmap
= (WXPixmap
) 0;
148 m_oldFont
= (WXFont
) 0;
151 wxWindowDC::wxWindowDC( wxWindow
*window
)
153 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
156 m_font
= window
->GetFont();
158 m_gcBacking
= (WXGC
) 0;
159 m_backgroundPixel
= -1;
160 m_currentPenWidth
= 1;
161 m_currentPenJoin
= -1;
162 m_currentPenDashCount
= -1;
163 m_currentPenDash
= (wxX11Dash
*) NULL
;
166 // m_currentBkMode = wxTRANSPARENT;
167 m_colour
= wxColourDisplay();
168 m_currentRegion
= (WXRegion
) 0;
169 m_userRegion
= (WXRegion
) 0;
173 m_display
= window
->GetXDisplay();
174 m_pixmap
= window
->GetXWindow();
175 Display
* display
= (Display
*) m_display
;
177 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
180 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
181 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
182 gcvalues
.graphics_exposures
= False
;
183 gcvalues
.subwindow_mode
= IncludeInferiors
;
184 gcvalues
.line_width
= 1;
185 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
186 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
189 if (m_window
->GetBackingPixmap())
191 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
192 DefaultScreen (display
)),
193 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
197 m_backgroundPixel
= (int) gcvalues
.background
;
199 // Get the current Font so we can set it back later
201 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
202 m_oldFont
= (WXFont
) valReturn
.font
;
204 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
207 wxWindowDC::~wxWindowDC()
209 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
211 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
213 if (m_window
&& m_window
->GetBackingPixmap())
214 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
218 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
222 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
223 m_gcBacking
= (WXGC
) 0;
226 XDestroyRegion ((Region
) m_currentRegion
);
227 m_currentRegion
= (WXRegion
) 0;
230 XDestroyRegion ((Region
) m_userRegion
);
231 m_userRegion
= (WXRegion
) 0;
234 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
235 const wxColour
& col
, int style
);
237 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
238 const wxColour
& col
, int style
)
240 return wxDoFloodFill(this, x
, y
, col
, style
);
243 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
245 // Generic (and therefore rather inefficient) method.
246 // Could be improved.
248 wxBitmap
bitmap(1, 1);
249 memdc
.SelectObject(bitmap
);
250 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
251 memdc
.SelectObject(wxNullBitmap
);
252 wxImage image
= bitmap
.ConvertToImage();
253 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
257 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
259 wxCHECK_RET( Ok(), "invalid dc" );
261 int x1d
, y1d
, x2d
, y2d
;
263 // FreeGetPixelCache();
273 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
275 if (m_window
&& m_window
->GetBackingPixmap())
276 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
277 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
278 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
280 CalcBoundingBox(x1
, y1
);
281 CalcBoundingBox(x2
, y2
);
284 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
286 wxCHECK_RET( Ok(), "invalid dc" );
291 int xx
= XLOG2DEV (x
);
292 int yy
= YLOG2DEV (y
);
294 wxDisplaySize (&ww
, &hh
);
295 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
297 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
300 if (m_window
&& m_window
->GetBackingPixmap())
304 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
307 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
313 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
315 wxCHECK_RET( Ok(), "invalid dc" );
317 // FreeGetPixelCache();
319 int xx1
= XLOG2DEV (x1
);
320 int yy1
= YLOG2DEV (y1
);
321 int xx2
= XLOG2DEV (x2
);
322 int yy2
= YLOG2DEV (y2
);
323 int xxc
= XLOG2DEV (xc
);
324 int yyc
= YLOG2DEV (yc
);
325 int xxc_2
= XLOG2DEV_2 (xc
);
326 int yyc_2
= YLOG2DEV_2 (yc
);
328 wxCoord dx
= xx1
- xxc
;
329 wxCoord dy
= yy1
- yyc
;
330 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
331 wxCoord r
= (wxCoord
) radius
;
333 double radius1
, radius2
;
335 if (xx1
== xx2
&& yy1
== yy2
)
340 else if (radius
== 0.0)
341 radius1
= radius2
= 0.0;
350 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
358 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
362 int alpha1
= (int) radius1
;
363 int alpha2
= (int) (radius2
- radius1
);
366 while (alpha2
> 360 * 64)
369 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
372 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
373 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
375 if (m_window
&& m_window
->GetBackingPixmap())
376 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
377 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
381 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
385 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
386 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
388 if (m_window
&& m_window
->GetBackingPixmap())
389 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
390 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
392 CalcBoundingBox (x1
, y1
);
393 CalcBoundingBox (x2
, y2
);
396 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
398 wxCHECK_RET( Ok(), "invalid dc" );
404 wd
= XLOG2DEVREL(width
);
405 hd
= YLOG2DEVREL(height
);
407 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
408 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
409 int start
= int(sa
*64);
410 int end
= int(ea
*64);
411 if (start
<0) start
+=360*64;
412 if (end
<0) end
+=360*64;
413 if (end
>start
) end
-=start
;
414 else end
+=360*64-start
;
416 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
418 m_autoSetting
= TRUE
; // must be reset
421 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
423 if (m_window
&& m_window
->GetBackingPixmap())
424 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
425 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
428 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
432 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
433 if (m_window
&& m_window
->GetBackingPixmap())
434 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
435 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
437 CalcBoundingBox (x
, y
);
438 CalcBoundingBox (x
+ width
, y
+ height
);
441 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
443 wxCHECK_RET( Ok(), "invalid dc" );
445 // FreeGetPixelCache();
447 if (m_pen
.Ok() && m_autoSetting
)
450 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
451 if (m_window
&& m_window
->GetBackingPixmap())
452 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
454 CalcBoundingBox (x
, y
);
457 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
459 wxCHECK_RET( Ok(), "invalid dc" );
461 // FreeGetPixelCache();
463 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
468 XPoint
*xpoints
= new XPoint
[n
];
471 for (i
= 0; i
< n
; i
++)
473 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
474 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
476 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
478 if (m_window
&& m_window
->GetBackingPixmap())
480 for (i
= 0; i
< n
; i
++)
482 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
483 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
485 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
491 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
492 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
494 wxCHECK_RET( Ok(), "invalid dc" );
496 // FreeGetPixelCache();
498 XPoint
*xpoints1
= new XPoint
[n
+ 1];
499 XPoint
*xpoints2
= new XPoint
[n
+ 1];
501 for (i
= 0; i
< n
; i
++)
503 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
504 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
505 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
506 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
507 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
510 // Close figure for XDrawLines (not needed for XFillPolygon)
511 xpoints1
[i
].x
= xpoints1
[0].x
;
512 xpoints1
[i
].y
= xpoints1
[0].y
;
513 xpoints2
[i
].x
= xpoints2
[0].x
;
514 xpoints2
[i
].y
= xpoints2
[0].y
;
516 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
519 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
520 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
521 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
522 if (m_window
&& m_window
->GetBackingPixmap())
524 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
525 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
526 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
527 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
531 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
535 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
537 if (m_window
&& m_window
->GetBackingPixmap())
538 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
545 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
547 wxCHECK_RET( Ok(), "invalid dc" );
549 // FreeGetPixelCache();
551 int xd
, yd
, wfd
, hfd
, wd
, hd
;
555 wfd
= XLOG2DEVREL(width
);
557 hfd
= YLOG2DEVREL(height
);
560 if (wfd
== 0 || hfd
== 0) return;
561 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
562 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
564 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
567 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
569 if (m_window
&& m_window
->GetBackingPixmap())
570 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
571 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
575 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
579 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
581 if (m_window
&& m_window
->GetBackingPixmap())
582 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
583 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
586 CalcBoundingBox (x
, y
);
587 CalcBoundingBox (x
+ width
, y
+ height
);
590 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
592 wxCHECK_RET( Ok(), "invalid dc" );
594 // FreeGetPixelCache();
596 // If radius is negative, it's a proportion of the smaller dimension.
598 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
600 int xd
= XLOG2DEV (x
);
601 int yd
= YLOG2DEV (y
);
602 int rd
= XLOG2DEVREL ((long) radius
);
603 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
604 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
609 // If radius is zero use DrawRectangle() instead to avoid
610 // X drawing errors with small radii
613 DrawRectangle( x
, y
, width
, height
);
617 // Draw nothing if transformed w or h is 0
618 if (wd
== 0 || hd
== 0) return;
620 // CMB: adjust size if outline is drawn otherwise the result is
621 // 1 pixel too wide and high
622 if (m_pen
.GetStyle() != wxTRANSPARENT
)
628 // CMB: ensure dd is not larger than rectangle otherwise we
629 // get an hour glass shape
630 if (rw_d
> wd
) rw_d
= wd
;
631 if (rw_d
> hd
) rw_d
= hd
;
634 // For backing pixmap
635 int xd2
= XLOG2DEV_2 (x
);
636 int yd2
= YLOG2DEV_2 (y
);
637 int rd2
= XLOG2DEVREL ((long) radius
);
638 int wd2
= XLOG2DEVREL (width
) ;
639 int hd2
= YLOG2DEVREL (height
) ;
644 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
648 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
650 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
653 // Arcs start from 3 o'clock, positive angles anticlockwise
655 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
656 rw_d
, rh_d
, 90 * 64, 90 * 64);
658 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
659 // rw_d, rh_d, 0, 90 * 64);
660 rw_d
, rh_d
, 0, 91 * 64);
662 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
664 // rw_d, rh_d, 270 * 64, 90 * 64);
665 rw_d
, rh_d
, 269 * 64, 92 * 64);
667 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
668 rw_d
, rh_d
, 180 * 64, 90 * 64);
670 if (m_window
&& m_window
->GetBackingPixmap())
672 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
673 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
674 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
675 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
677 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
678 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
679 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
680 xd2
+ wd2
- rw_d2
, yd2
,
681 // rw_d2, rh_d2, 0, 90 * 64);
682 rw_d2
, rh_d2
, 0, 91 * 64);
683 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
686 // rw_d2, rh_d2, 270 * 64, 90 * 64);
687 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
688 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
689 xd2
, yd2
+ hd2
- rh_d2
,
690 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
694 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
697 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
698 xd
+ wd
- rd
+ 1, yd
);
699 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
700 xd
+ wd
- rd
, yd
+ hd
);
702 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
704 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
705 xd
+ wd
, yd
+ hd
- rd
+ 1);
706 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
707 rw_d
, rh_d
, 90 * 64, 90 * 64);
708 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
709 // rw_d, rh_d, 0, 90 * 64);
710 rw_d
, rh_d
, 0, 91 * 64);
711 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
713 rw_d
, rh_d
, 269 * 64, 92 * 64);
714 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
715 rw_d
, rh_d
, 180 * 64, 90 * 64);
717 if (m_window
&& m_window
->GetBackingPixmap())
719 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
721 xd2
+ wd2
- rd2
+ 1, yd2
);
722 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
723 xd2
+ rd2
, yd2
+ hd2
,
724 xd2
+ wd2
- rd2
, yd2
+ hd2
);
726 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
728 xd2
, yd2
+ hd2
- rd2
);
729 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
730 xd2
+ wd2
, yd2
+ rd2
,
731 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
732 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
734 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
735 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
736 xd2
+ wd2
- rw_d2
, yd2
,
737 // rw_d2, rh_d2, 0, 90 * 64);
738 rw_d2
, rh_d2
, 0, 91 * 64);
739 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
742 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
743 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
744 xd2
, yd2
+ hd2
- rh_d2
,
745 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
748 CalcBoundingBox (x
, y
);
749 CalcBoundingBox (x
+ width
, y
+ height
);
754 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
756 wxCHECK_RET( Ok(), "invalid dc" );
758 // Check for negative width and height
771 // FreeGetPixelCache();
773 static const int angle
= 23040;
779 wd
= XLOG2DEVREL(width
) ;
780 hd
= YLOG2DEVREL(height
) ;
782 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
785 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
786 if (m_window
&& m_window
->GetBackingPixmap())
787 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
788 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
789 XLOG2DEVREL (width
) - WX_GC_CF
,
790 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
793 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
797 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
798 if (m_window
&& m_window
->GetBackingPixmap())
799 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
800 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
801 XLOG2DEVREL (width
) - WX_GC_CF
,
802 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
804 CalcBoundingBox (x
, y
);
805 CalcBoundingBox (x
+ width
, y
+ height
);
809 bool wxWindowDC::CanDrawBitmap() const
811 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
817 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
819 // FreeGetPixelCache();
821 // Be sure that foreground pixels (1) of
822 // the Icon will be painted with pen colour. [m_pen.SetColour()]
823 // Background pixels (0) will be painted with
824 // last selected background color. [::SetBackground]
825 if (m_pen
.Ok() && m_autoSetting
)
829 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
830 width
= icon
.GetWidth();
831 height
= icon
.GetHeight();
832 if (icon
.GetDisplay() == m_display
)
834 if (icon
.GetDepth() <= 1)
836 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
838 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
842 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
844 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
848 if (m_window
&& m_window
->GetBackingPixmap())
850 if (icon
.GetDepth() <= 1)
852 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
853 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
857 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
859 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
862 } else { /* Remote copy (different (Display*) m_displays) */
863 XImage
*cache
= NULL
;
864 if (m_window
&& m_window
->GetBackingPixmap())
865 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
866 (GC
) m_gcBacking
, 0, 0, width
, height
,
867 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
868 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
870 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
872 CalcBoundingBox (x
, y
);
876 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
877 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
878 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
879 wxCoord xsrcMask
, wxCoord ysrcMask
)
881 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
883 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
885 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
887 // FreeGetPixelCache();
889 // Be sure that foreground pixels (1) of the Icon will be painted with
890 // foreground colour. [m_textForegroundColour] Background pixels (0)
891 // will be painted with backgound colour (m_textBackgroundColour)
892 // Using ::SetPen is horribly slow, so avoid doing it
893 int oldBackgroundPixel
= -1;
894 int oldForegroundPixel
= -1;
896 if (m_textBackgroundColour
.Ok())
898 oldBackgroundPixel
= m_backgroundPixel
;
899 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
901 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
902 if (m_window
&& m_window
->GetBackingPixmap())
903 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
906 if (m_textForegroundColour
.Ok())
908 oldForegroundPixel
= m_currentColour
.GetPixel();
910 if( m_textForegroundColour
.GetPixel() <= -1 )
911 CalculatePixel( m_textForegroundColour
,
912 m_textForegroundColour
, TRUE
);
914 int pixel
= m_textForegroundColour
.GetPixel();
916 SetForegroundPixelWithLogicalFunction(pixel
);
919 // Do bitmap scaling if necessary
921 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
922 Pixmap sourcePixmap
= (Pixmap
) NULL
;
923 double scaleX
, scaleY
;
924 GetUserScale(& scaleX
, & scaleY
);
927 /* TODO: use the mask origin when drawing transparently */
928 if (xsrcMask
== -1 && ysrcMask
== -1)
930 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
933 // Sorry, can't scale masks just yet
934 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
936 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
937 wxBitmap
& bitmap
= memDC
->GetBitmap();
939 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
941 wxImage image
= bitmap
.ConvertToImage();
944 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
948 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
949 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
951 image
= image
.Scale(scaledW
, scaledH
);
952 scaledBitmap
= new wxBitmap(image
);
953 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
957 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
959 if (m_pixmap
&& sourcePixmap
)
962 int orig
= m_logicalFunction
;
964 SetLogicalFunction (rop
);
966 if (m_display
!= sourceDC
->m_display
)
968 XImage
*cache
= NULL
;
970 if (m_window
&& m_window
->GetBackingPixmap())
971 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
972 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
974 source
->LogicalToDeviceX (xsrc
),
975 source
->LogicalToDeviceY (ysrc
),
976 source
->LogicalToDeviceXRel(width
),
977 source
->LogicalToDeviceYRel(height
),
978 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
981 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
983 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
984 wxBitmap
& sel
= memDC
->GetBitmap();
985 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
987 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
988 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
992 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
993 source
->LogicalToDeviceX (xsrc
),
994 source
->LogicalToDeviceY (ysrc
),
995 source
->LogicalToDeviceXRel(width
),
996 source
->LogicalToDeviceYRel(height
),
997 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
1002 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1003 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1007 { //XGCValues values;
1008 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
1010 if (m_window
&& m_window
->GetBackingPixmap())
1012 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
1013 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
1015 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1016 source
->LogicalToDeviceX (xsrc
),
1017 source
->LogicalToDeviceY (ysrc
),
1018 source
->LogicalToDeviceXRel(width
),
1019 source
->LogicalToDeviceYRel(height
),
1020 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
1024 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1025 source
->LogicalToDeviceX (xsrc
),
1026 source
->LogicalToDeviceY (ysrc
),
1027 source
->LogicalToDeviceXRel(width
),
1028 source
->LogicalToDeviceYRel(height
),
1029 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
1032 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1034 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1035 wxBitmap
& sel
= memDC
->GetBitmap();
1036 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1038 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1039 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1043 // Check if we're copying from a mono bitmap
1044 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1045 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1047 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1048 source
->LogicalToDeviceX (xsrc
),
1049 source
->LogicalToDeviceY (ysrc
),
1050 source
->LogicalToDeviceXRel(width
),
1051 source
->LogicalToDeviceYRel(height
),
1052 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1056 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1057 source
->LogicalToDeviceX (xsrc
),
1058 source
->LogicalToDeviceY (ysrc
),
1059 source
->LogicalToDeviceXRel(width
),
1060 source
->LogicalToDeviceYRel(height
),
1061 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1066 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1067 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1070 } /* Remote/local (Display*) m_display */
1071 CalcBoundingBox (xdest
, ydest
);
1072 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1074 SetLogicalFunction(orig
);
1078 if (scaledBitmap
) delete scaledBitmap
;
1080 if (oldBackgroundPixel
> -1)
1082 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1083 if (m_window
&& m_window
->GetBackingPixmap())
1084 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1085 oldBackgroundPixel
);
1087 if (oldForegroundPixel
> -1)
1089 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1090 if (m_window
&& m_window
->GetBackingPixmap())
1091 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1092 oldForegroundPixel
);
1098 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1100 wxCHECK_RET( Ok(), "invalid dc" );
1102 // Since X draws from the baseline of the text, must add the text height
1108 // Set FillStyle, otherwise X will use current stipple!
1109 XGCValues gcV
, gcBackingV
;
1111 XGetGCValues ((Display
*) m_display
, (GC
)m_gc
, GCFillStyle
, &gcV
);
1112 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1113 if (m_window
&& m_window
->GetBackingPixmap())
1115 XGetGCValues ((Display
*) m_display
, (GC
)m_gcBacking
, GCFillStyle
,
1117 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
, FillSolid
);
1120 slen
= strlen(text
);
1124 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1125 int direction
, descent
;
1126 XCharStruct overall_return
;
1129 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1130 &ascent
, &descent
, &overall_return
);
1133 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1134 &ascent
, &descent
, &overall_return
);
1136 cx
= overall_return
.width
;
1137 cy
= ascent
+ descent
;
1140 // First draw a rectangle representing the text background, if a text
1141 // background is specified
1142 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1144 wxColour oldPenColour
= m_currentColour
;
1145 m_currentColour
= m_textBackgroundColour
;
1146 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1147 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1148 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1149 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1151 // This separation of the big && test required for gcc2.7/HP UX 9.02
1152 // or pixel value can be corrupted!
1153 sameColour
= (sameColour
&&
1154 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1156 if (!sameColour
|| !GetOptimization())
1158 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1159 m_currentColour
= m_textBackgroundColour
;
1161 // Set the GC to the required colour
1164 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1165 if (m_window
&& m_window
->GetBackingPixmap())
1166 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1170 m_textBackgroundColour
= oldPenColour
;
1172 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1173 if (m_window
&& m_window
->GetBackingPixmap())
1174 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1175 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1178 // Now set the text foreground and draw the text
1179 if (m_textForegroundColour
.Ok ())
1181 wxColour oldPenColour
= m_currentColour
;
1182 m_currentColour
= m_textForegroundColour
;
1183 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1184 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1185 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1186 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1187 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1189 if (!sameColour
|| !GetOptimization())
1191 int pixel
= CalculatePixel(m_textForegroundColour
,
1192 m_currentColour
, FALSE
);
1194 // Set the GC to the required colour
1197 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1198 if (m_window
&& m_window
->GetBackingPixmap())
1199 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1203 m_textForegroundColour
= oldPenColour
;
1206 // We need to add the ascent, not the whole height, since X draws at the
1207 // point above the descender.
1210 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1211 (XChar2b
*)(char*) (const char*) text
, slen
);
1214 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1216 if (m_window
&& m_window
->GetBackingPixmap()) {
1219 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1220 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1221 (XChar2b
*)(char*) (const char*) text
, slen
);
1224 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1225 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1228 // restore fill style
1229 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, gcV
.fill_style
);
1230 if (m_window
&& m_window
->GetBackingPixmap())
1231 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
,
1232 gcBackingV
.fill_style
);
1235 GetTextExtent (text
, &w
, &h
);
1236 CalcBoundingBox (x
+ w
, y
+ h
);
1237 CalcBoundingBox (x
, y
);
1240 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
,
1245 DrawText(text
, x
, y
);
1249 wxCHECK_RET( Ok(), "invalid dc" );
1251 int oldBackgroundPixel
= -1;
1252 int oldForegroundPixel
= -1;
1253 int foregroundPixel
= -1;
1254 int backgroundPixel
= -1;
1256 if (m_textBackgroundColour
.Ok())
1258 oldBackgroundPixel
= m_backgroundPixel
;
1259 backgroundPixel
= m_textBackgroundColour
.AllocColour(m_display
);
1261 if (m_textForegroundColour
.Ok())
1263 oldForegroundPixel
= m_currentColour
.GetPixel();
1265 if( m_textForegroundColour
.GetPixel() <= -1 )
1266 CalculatePixel( m_textForegroundColour
,
1267 m_textForegroundColour
, TRUE
);
1269 foregroundPixel
= m_textForegroundColour
.GetPixel();
1272 // Since X draws from the baseline of the text, must add the text height
1276 int slen
= text
.length();
1280 // Calculate text extent.
1281 WXFontStructPtr pFontStruct
=
1282 m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1283 int direction
, descent
;
1284 XCharStruct overall_return
;
1287 (void)XTextExtents16((XFontStruct
*) pFontStruct
,
1288 (XChar2b
*)(const char*) text
,
1290 &ascent
, &descent
, &overall_return
);
1293 (void)XTextExtents((XFontStruct
*) pFontStruct
,
1294 (char*)text
.c_str(), slen
, &direction
,
1295 &ascent
, &descent
, &overall_return
);
1297 cx
= overall_return
.width
;
1298 cy
= ascent
+ descent
;
1301 wxBitmap
src(cx
, cy
);
1303 dc
.SelectObject(src
);
1304 dc
.SetFont(GetFont());
1305 dc
.SetBackground(*wxWHITE_BRUSH
);
1306 dc
.SetBrush(*wxBLACK_BRUSH
);
1308 dc
.DrawText(text
, 0, 0);
1309 dc
.SetFont(wxNullFont
);
1311 // Calculate the size of the rotated bounding box.
1312 double dx
= cos(angle
/ 180.0 * M_PI
);
1313 double dy
= sin(angle
/ 180.0 * M_PI
);
1314 double x4
= cy
* dy
;
1315 double y4
= cy
* dx
;
1316 double x3
= cx
* dx
;
1317 double y3
= -cx
* dy
;
1318 double x2
= x3
+ x4
;
1319 double y2
= y3
+ y4
;
1323 // Create image from the source bitmap after writing the text into it.
1324 wxImage image
= src
.ConvertToImage();
1326 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1327 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1328 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1329 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1331 bool lastFore
= false, lastBack
= false;
1333 // This rotates counterclockwise around the top left corner.
1334 for (int rx
= minx
; rx
< maxx
; rx
++)
1336 for (int ry
= miny
; ry
< maxy
; ry
++)
1338 // transform dest coords to source coords
1339 int sx
= (int) (rx
* dx
- ry
* dy
+ 0.5);
1340 int sy
= - (int) (-ry
* dx
- rx
* dy
+ 0.5);
1341 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1343 bool textPixel
= image
.GetRed(sx
, sy
) == 0;
1345 if (!textPixel
&& m_backgroundMode
!= wxSOLID
)
1348 wxCoord ox
= (wxCoord
) (x1
+ rx
),
1349 oy
= (wxCoord
) (y1
+ ry
);
1350 // draw black pixels, ignore white ones (i.e. transparent b/g)
1351 if (textPixel
&& !lastFore
)
1353 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1358 else if (!textPixel
&& !lastBack
)
1360 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1366 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
,
1367 (GC
) m_gc
, XLOG2DEV (ox
), YLOG2DEV (oy
));
1368 if (m_window
&& m_window
->GetBackingPixmap())
1369 XDrawPoint ((Display
*) m_display
,
1370 (Pixmap
) m_window
->GetBackingPixmap(),
1372 XLOG2DEV_2 (ox
), YLOG2DEV_2 (oy
));
1377 if (oldBackgroundPixel
> -1)
1379 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1380 if (m_window
&& m_window
->GetBackingPixmap())
1381 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1382 oldBackgroundPixel
);
1384 if (oldForegroundPixel
> -1)
1386 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1387 if (m_window
&& m_window
->GetBackingPixmap())
1388 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1389 oldForegroundPixel
);
1392 CalcBoundingBox (minx
, miny
);
1393 CalcBoundingBox (maxx
, maxy
);
1396 bool wxWindowDC::CanGetTextExtent() const
1401 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1402 wxCoord
*descent
, wxCoord
*externalLeading
,
1403 wxFont
*font
) const
1405 wxCHECK_RET( Ok(), "invalid dc" );
1407 wxFont
* theFont
= font
;
1409 theFont
= (wxFont
*)&m_font
; // const_cast
1413 // TODO: this should be an error log function
1414 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1416 if (width
) *width
= -1;
1417 if (height
) *height
= -1;
1421 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1423 int direction
, ascent
, descent2
;
1424 XCharStruct overall
;
1429 slen
= str16len(string
);
1432 slen
= strlen(string
);
1436 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1437 &ascent
, &descent2
, &overall
);
1440 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1441 &ascent
, &descent2
, &overall
);
1443 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1444 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1446 *descent
= descent2
;
1447 if (externalLeading
)
1448 *externalLeading
= 0;
1451 wxCoord
wxWindowDC::GetCharWidth() const
1453 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1454 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1456 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1458 int direction
, ascent
, descent
;
1459 XCharStruct overall
;
1460 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1461 &descent
, &overall
);
1462 return XDEV2LOGREL(overall
.width
);
1465 wxCoord
wxWindowDC::GetCharHeight() const
1467 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1468 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1470 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1472 int direction
, ascent
, descent
;
1473 XCharStruct overall
;
1474 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1475 &descent
, &overall
);
1476 // return XDEV2LOGREL(overall.ascent + overall.descent);
1477 return XDEV2LOGREL(ascent
+ descent
);
1480 void wxWindowDC::Clear()
1482 wxCHECK_RET( Ok(), "invalid dc" );
1487 m_window
->GetSize(&w
, &h
);
1489 if (m_window
&& m_window
->GetBackingPixmap())
1491 w
= m_window
->GetPixmapWidth();
1492 h
= m_window
->GetPixmapHeight();
1497 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1499 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1500 w
= memDC
->GetBitmap().GetWidth();
1501 h
= memDC
->GetBitmap().GetHeight();
1507 wxBrush saveBrush
= m_brush
;
1508 SetBrush (m_backgroundBrush
);
1510 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1512 if (m_window
&& m_window
->GetBackingPixmap())
1513 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1515 m_brush
= saveBrush
;
1518 void wxWindowDC::Clear(const wxRect
& rect
)
1520 wxCHECK_RET( Ok(), "invalid dc" );
1522 int x
= rect
.x
; int y
= rect
.y
;
1523 int w
= rect
.width
; int h
= rect
.height
;
1525 wxBrush saveBrush
= m_brush
;
1526 SetBrush (m_backgroundBrush
);
1528 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1530 if (m_window
&& m_window
->GetBackingPixmap())
1531 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1533 m_brush
= saveBrush
;
1536 void wxWindowDC::SetFont( const wxFont
&font
)
1538 wxCHECK_RET( Ok(), "invalid dc" );
1544 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1546 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1548 if (m_window
&& m_window
->GetBackingPixmap())
1549 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1554 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1556 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1557 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1559 if (m_window
&& m_window
->GetBackingPixmap())
1560 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1563 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel
)
1565 if (m_logicalFunction
== wxXOR
)
1568 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1569 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1570 pixel
^ values
.background
);
1571 if (m_window
&& m_window
->GetBackingPixmap())
1572 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1573 pixel
^ values
.background
);
1577 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1578 if (m_window
&& m_window
->GetBackingPixmap())
1579 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1583 int wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1584 bool roundToWhite
) const
1586 const unsigned char wp
= (unsigned char)255;
1589 if(!m_colour
) // Mono display
1591 unsigned char red
= colour
.Red ();
1592 unsigned char blue
= colour
.Blue ();
1593 unsigned char green
= colour
.Green ();
1595 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1596 // not black and roundToWhite was specified
1597 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1600 pixel
= (int)WhitePixel((Display
*) m_display
,
1601 DefaultScreen((Display
*) m_display
));
1602 curCol
.SetPixel(pixel
);
1603 colour
.SetPixel(pixel
);
1608 pixel
= (int)BlackPixel((Display
*) m_display
,
1609 DefaultScreen((Display
*) m_display
));
1610 curCol
.SetPixel(pixel
);
1611 colour
.SetPixel(pixel
);
1617 pixel
= colour
.AllocColour((Display
*) m_display
);
1618 curCol
.SetPixel(pixel
);
1624 void wxWindowDC::SetPen( const wxPen
&pen
)
1626 wxCHECK_RET( Ok(), "invalid dc" );
1632 wxBitmap oldStipple
= m_currentStipple
;
1633 int oldStyle
= m_currentStyle
;
1634 int oldFill
= m_currentFill
;
1635 int old_pen_width
= m_currentPenWidth
;
1636 int old_pen_join
= m_currentPenJoin
;
1637 int old_pen_cap
= m_currentPenCap
;
1638 int old_pen_nb_dash
= m_currentPenDashCount
;
1639 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1641 wxColour oldPenColour
= m_currentColour
;
1642 m_currentColour
= m_pen
.GetColour ();
1643 m_currentStyle
= m_pen
.GetStyle ();
1644 m_currentFill
= m_pen
.GetStyle (); // TODO?
1645 m_currentPenWidth
= m_pen
.GetWidth ();
1646 m_currentPenJoin
= m_pen
.GetJoin ();
1647 m_currentPenCap
= m_pen
.GetCap ();
1648 m_currentPenDashCount
= m_pen
.GetDashCount();
1649 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1651 if (m_currentStyle
== wxSTIPPLE
)
1652 m_currentStipple
= * m_pen
.GetStipple ();
1654 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1655 oldFill
== m_currentFill
&&
1656 old_pen_join
== m_currentPenJoin
&&
1657 old_pen_cap
== m_currentPenCap
&&
1658 old_pen_nb_dash
== m_currentPenDashCount
&&
1659 old_pen_dash
== m_currentPenDash
&&
1660 old_pen_width
== m_currentPenWidth
);
1662 bool sameColour
= (oldPenColour
.Ok () &&
1663 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1664 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1665 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1666 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1668 if (!sameStyle
|| !GetOptimization())
1670 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1671 if (scaled_width
< 0)
1677 static const wxX11Dash dotted
[] = {2, 5};
1678 static const wxX11Dash short_dashed
[] = {4, 4};
1679 static const wxX11Dash long_dashed
[] = {4, 8};
1680 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1682 // We express dash pattern in pen width unit, so we are
1683 // independent of zoom factor and so on...
1685 const wxX11Dash
*req_dash
;
1687 switch (m_pen
.GetStyle ())
1690 req_nb_dash
= m_currentPenDashCount
;
1691 req_dash
= m_currentPenDash
;
1692 style
= LineOnOffDash
;
1697 style
= LineOnOffDash
;
1701 req_dash
= short_dashed
;
1702 style
= LineOnOffDash
;
1706 req_dash
= long_dashed
;
1707 style
= LineOnOffDash
;
1711 req_dash
= dotted_dashed
;
1712 style
= LineOnOffDash
;
1719 req_dash
= (wxX11Dash
*)NULL
;
1723 if (req_dash
&& req_nb_dash
)
1725 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1728 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1729 for (int i
= 0; i
< req_nb_dash
; i
++)
1730 real_req_dash
[i
] = req_dash
[i
] * factor
;
1731 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1733 if (m_window
&& m_window
->GetBackingPixmap())
1734 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1735 delete[]real_req_dash
;
1739 // No Memory. We use non-scaled dash pattern...
1740 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1742 if (m_window
&& m_window
->GetBackingPixmap())
1743 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1747 switch (m_pen
.GetCap ())
1749 case wxCAP_PROJECTING
:
1750 cap
= CapProjecting
;
1757 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1761 switch (m_pen
.GetJoin ())
1775 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1777 if (m_window
&& m_window
->GetBackingPixmap())
1778 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1781 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1785 oldStipple
= wxNullBitmap
; // For later reset!!
1787 switch (m_currentFill
)
1789 case wxBDIAGONAL_HATCH
:
1790 if (bdiag
== (Pixmap
) 0)
1791 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1792 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1793 bdiag_bits
, bdiag_width
, bdiag_height
);
1796 case wxFDIAGONAL_HATCH
:
1797 if (fdiag
== (Pixmap
) 0)
1798 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1799 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1800 fdiag_bits
, fdiag_width
, fdiag_height
);
1804 if (cross
== (Pixmap
) 0)
1805 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1806 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1807 cross_bits
, cross_width
, cross_height
);
1810 case wxHORIZONTAL_HATCH
:
1811 if (horiz
== (Pixmap
) 0)
1812 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1813 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1814 horiz_bits
, horiz_width
, horiz_height
);
1817 case wxVERTICAL_HATCH
:
1818 if (verti
== (Pixmap
) 0)
1819 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1820 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1821 verti_bits
, verti_width
, verti_height
);
1824 case wxCROSSDIAG_HATCH
:
1826 if (cdiag
== (Pixmap
) 0)
1827 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1828 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1829 cdiag_bits
, cdiag_width
, cdiag_height
);
1833 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1835 if (m_window
&& m_window
->GetBackingPixmap())
1836 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1838 else if (m_currentStipple
.Ok()
1839 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1841 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1843 if (m_window
&& m_window
->GetBackingPixmap())
1844 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1847 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1851 if (m_currentFill
== wxSTIPPLE
)
1852 fill_style
= FillStippled
;
1853 else if (IS_HATCH (m_currentFill
))
1854 fill_style
= FillStippled
;
1856 fill_style
= FillSolid
;
1857 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1858 if (m_window
&& m_window
->GetBackingPixmap())
1859 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1862 // must test m_logicalFunction, because it involves background!
1863 if (!sameColour
|| !GetOptimization()
1864 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1867 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1868 pixel
= m_backgroundPixel
;
1871 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, FALSE
);
1874 // Finally, set the GC to the required colour
1876 SetForegroundPixelWithLogicalFunction(pixel
);
1879 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1884 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1886 wxCHECK_RET( Ok(), "invalid dc" );
1890 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1893 int oldFill
= m_currentFill
;
1894 wxBitmap oldStipple
= m_currentStipple
;
1896 m_autoSetting
|= 0x1;
1898 m_currentFill
= m_brush
.GetStyle ();
1899 if (m_currentFill
== wxSTIPPLE
)
1900 m_currentStipple
= * m_brush
.GetStipple ();
1902 wxColour
oldBrushColour(m_currentColour
);
1903 m_currentColour
= m_brush
.GetColour ();
1905 bool sameColour
= (oldBrushColour
.Ok () &&
1906 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1907 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1908 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1909 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1911 int stippleDepth
= -1;
1913 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1915 switch (brush
.GetStyle ())
1920 stippleDepth
= m_currentStipple
.GetDepth();
1922 case wxBDIAGONAL_HATCH
:
1923 case wxCROSSDIAG_HATCH
:
1924 case wxFDIAGONAL_HATCH
:
1926 case wxHORIZONTAL_HATCH
:
1927 case wxVERTICAL_HATCH
:
1929 if (stippleDepth
== -1) stippleDepth
= 1;
1931 // Chris Breeze 23/07/97: use background mode to
1932 // determine whether fill style should be solid or
1934 int style
= stippleDepth
== 1 ?
1935 (m_backgroundMode
== wxSOLID
?
1936 FillOpaqueStippled
: FillStippled
) :
1938 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1939 if (m_window
&& m_window
->GetBackingPixmap())
1940 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1945 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1946 if (m_window
&& m_window
->GetBackingPixmap())
1947 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
,
1952 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1956 switch (m_currentFill
)
1958 case wxBDIAGONAL_HATCH
:
1959 if (bdiag
== (Pixmap
) 0)
1960 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1961 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1962 bdiag_bits
, bdiag_width
, bdiag_height
);
1965 case wxFDIAGONAL_HATCH
:
1966 if (fdiag
== (Pixmap
) 0)
1967 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1968 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1969 fdiag_bits
, fdiag_width
, fdiag_height
);
1973 if (cross
== (Pixmap
) 0)
1974 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1975 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1976 cross_bits
, cross_width
, cross_height
);
1979 case wxHORIZONTAL_HATCH
:
1980 if (horiz
== (Pixmap
) 0)
1981 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1982 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1983 horiz_bits
, horiz_width
, horiz_height
);
1986 case wxVERTICAL_HATCH
:
1987 if (verti
== (Pixmap
) 0)
1988 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1989 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1990 verti_bits
, verti_width
, verti_height
);
1993 case wxCROSSDIAG_HATCH
:
1995 if (cdiag
== (Pixmap
) 0)
1996 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1997 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1998 cdiag_bits
, cdiag_width
, cdiag_height
);
2002 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
2004 if (m_window
&& m_window
->GetBackingPixmap())
2005 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
2007 // X can forget the stipple value when resizing a window (apparently)
2008 // so always set the stipple.
2009 else if (m_currentFill
!= wxSOLID
&& m_currentFill
!= wxTRANSPARENT
&&
2010 m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
2012 if (m_currentStipple
.GetDepth() == 1)
2014 XSetStipple ((Display
*) m_display
, (GC
) m_gc
,
2015 (Pixmap
) m_currentStipple
.GetPixmap());
2016 if (m_window
&& m_window
->GetBackingPixmap())
2017 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
,
2018 (Pixmap
) m_currentStipple
.GetPixmap());
2022 XSetTile ((Display
*) m_display
, (GC
) m_gc
,
2023 (Pixmap
) m_currentStipple
.GetPixmap());
2024 if (m_window
&& m_window
->GetBackingPixmap())
2025 XSetTile ((Display
*) m_display
,(GC
) m_gcBacking
,
2026 (Pixmap
) m_currentStipple
.GetPixmap());
2030 // must test m_logicalFunction, because it involves background!
2031 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
2033 int pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, TRUE
);
2036 SetForegroundPixelWithLogicalFunction(pixel
);
2039 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
2042 void wxWindowDC::SetBackground( const wxBrush
&brush
)
2044 wxCHECK_RET( Ok(), "invalid dc" );
2046 m_backgroundBrush
= brush
;
2048 if (!m_backgroundBrush
.Ok())
2051 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
2053 // New behaviour, 10/2/99: setting the background brush of a DC
2054 // doesn't affect the window background colour.
2056 // XSetWindowBackground doesn't work for non-Window pixmaps
2057 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2058 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2061 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2062 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2063 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
2064 if (m_window
&& m_window
->GetBackingPixmap())
2065 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
2069 void wxWindowDC::SetLogicalFunction( int function
)
2071 wxCHECK_RET( Ok(), "invalid dc" );
2076 if (m_logicalFunction
== function
)
2082 x_function
= GXclear
;
2088 x_function
= GXinvert
;
2091 x_function
= GXorReverse
;
2094 x_function
= GXandReverse
;
2103 x_function
= GXandInverted
;
2106 x_function
= GXnoop
;
2112 x_function
= GXequiv
;
2115 x_function
= GXcopyInverted
;
2118 x_function
= GXorInverted
;
2121 x_function
= GXnand
;
2128 x_function
= GXcopy
;
2132 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2133 if (m_window
&& m_window
->GetBackingPixmap())
2134 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2136 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2137 /* MATTHEW: [9] Need to redo pen simply */
2138 m_autoSetting
|= 0x2;
2140 m_logicalFunction
= function
;
2144 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2146 wxCHECK_RET( Ok(), "invalid dc" );
2148 if (m_textForegroundColour
== col
)
2151 m_textForegroundColour
= col
;
2155 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2157 wxCHECK_RET( Ok(), "invalid dc" );
2159 if (m_textBackgroundColour
== col
)
2162 m_textBackgroundColour
= col
;
2163 if (!m_textBackgroundColour
.Ok())
2167 void wxWindowDC::SetBackgroundMode( int mode
)
2169 m_backgroundMode
= mode
;
2172 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2177 /* Use GetXColormap */
2178 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2179 (Colormap
) palette
.GetXColormap());
2181 /* Use wxGetMainColormap */
2182 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2183 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2188 void wxWindowDC::SetDCClipping()
2190 // m_userRegion is the region set by calling SetClippingRegion
2192 if (m_currentRegion
)
2193 XDestroyRegion ((Region
) m_currentRegion
);
2195 // We need to take into account
2196 // clipping imposed on a window by a repaint.
2197 // We'll combine it with the user region. But for now,
2198 // just use the currently-defined user clipping region.
2199 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2200 m_currentRegion
= (WXRegion
) XCreateRegion ();
2202 m_currentRegion
= (WXRegion
) NULL
;
2204 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2205 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2206 else if (m_userRegion
)
2207 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2208 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2209 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2210 (Region
) m_currentRegion
);
2212 if (m_currentRegion
)
2214 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2218 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2223 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2225 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2228 XDestroyRegion ((Region
) m_userRegion
);
2229 m_userRegion
= (WXRegion
) XCreateRegion ();
2233 r
.width
= XLOG2DEVREL(width
);
2234 r
.height
= YLOG2DEVREL(height
);
2235 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2239 // Needs to work differently for Pixmap: without this,
2240 // there's a nasty (Display*) m_display bug. 8/12/94
2241 if (m_window
&& m_window
->GetBackingPixmap())
2243 XRectangle rects
[1];
2244 rects
[0].x
= XLOG2DEV_2(x
);
2245 rects
[0].y
= YLOG2DEV_2(y
);
2246 rects
[0].width
= XLOG2DEVREL(width
);
2247 rects
[0].height
= YLOG2DEVREL(height
);
2248 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2252 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2254 wxRect box
= region
.GetBox();
2256 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2259 XDestroyRegion ((Region
) m_userRegion
);
2260 m_userRegion
= (WXRegion
) XCreateRegion ();
2262 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2266 // Needs to work differently for Pixmap: without this,
2267 // there's a nasty (Display*) m_display bug. 8/12/94
2268 if (m_window
&& m_window
->GetBackingPixmap())
2270 XRectangle rects
[1];
2271 rects
[0].x
= XLOG2DEV_2(box
.x
);
2272 rects
[0].y
= YLOG2DEV_2(box
.y
);
2273 rects
[0].width
= XLOG2DEVREL(box
.width
);
2274 rects
[0].height
= YLOG2DEVREL(box
.height
);
2275 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2280 void wxWindowDC::DestroyClippingRegion()
2282 wxDC::DestroyClippingRegion();
2285 XDestroyRegion ((Region
) m_userRegion
);
2286 m_userRegion
= NULL
;
2291 gc_val
.clip_mask
= None
;
2292 if (m_window
&& m_window
->GetBackingPixmap())
2293 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2296 // Resolution in pixels per logical inch
2297 wxSize
wxWindowDC::GetPPI() const
2299 return wxSize(100, 100);
2302 int wxWindowDC::GetDepth() const
2311 // ----------------------------------------------------------------------------
2313 // ----------------------------------------------------------------------------
2315 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2317 wxRegion
* region
= NULL
;
2319 // Combine all the update rects into a region
2320 const wxRectList
& updateRects(win
->GetUpdateRects());
2321 if ( updateRects
.GetCount() != 0 )
2323 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2325 node
= node
->GetNext() )
2327 wxRect
* rect
= node
->GetData();
2330 region
= new wxRegion(*rect
);
2332 // TODO: is this correct? In SetDCClipping above,
2333 // XIntersectRegion is used to combine paint and user
2334 // regions. XIntersectRegion appears to work in that case...
2335 region
->Union(*rect
);
2341 win
->GetClientSize(&cw
, &ch
);
2342 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2345 win
->SetUpdateRegion(*region
);
2347 wxRegion
& theRegion(win
->GetUpdateRegion());
2348 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2350 // Set the clipping region. Any user-defined region will be combined with this
2351 // one in SetDCClipping.
2352 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2357 wxPaintDC::~wxPaintDC()
2359 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2361 m_window
->ClearUpdateRegion();
2364 // ----------------------------------------------------------------------------
2365 // private functions
2366 // ----------------------------------------------------------------------------
2369 Used when copying between drawables on different (Display*) m_displays. Not
2370 very fast, but better than giving up.
2373 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2374 Drawable src
, Drawable dest
,
2377 unsigned int w
, unsigned int h
,
2378 int destx
, int desty
,
2379 bool more
, XImage
**cache
)
2381 XImage
*image
, *destimage
;
2382 Colormap destcm
, srccm
;
2383 static const int CACHE_SIZE
= 256;
2386 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2387 int k
, cache_pos
, all_cache
;
2389 if (!cache
|| !*cache
)
2390 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2394 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2396 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2397 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2402 for (i
= 0; i
< w
; i
++)
2403 for (j
= 0; j
< h
; j
++) {
2404 unsigned long pixel
;
2407 pixel
= XGetPixel(image
, i
, j
);
2408 for (k
= cache_pos
; k
--; )
2409 if (cachesrc
[k
] == pixel
) {
2410 pixel
= cachedest
[k
];
2414 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2415 if (cachesrc
[k
] == pixel
) {
2416 pixel
= cachedest
[k
];
2420 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2421 XQueryColor(src_display
, srccm
, &xcol
);
2422 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2424 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2426 if (++cache_pos
>= CACHE_SIZE
) {
2432 XPutPixel(destimage
, i
, j
, pixel
);
2435 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2436 XDestroyImage(destimage
);
2441 XDestroyImage(image
);
2446 /* Helper function for 16-bit fonts */
2447 static int str16len(const char *s
)
2451 while (s
[0] && s
[1]) {