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 void wxWindowDC::Init()
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_colour
= wxColourDisplay();
142 m_display
= (WXDisplay
*) NULL
;
143 m_currentRegion
= (WXRegion
) 0;
144 m_userRegion
= (WXRegion
) 0;
145 m_pixmap
= (WXPixmap
) 0;
147 m_oldFont
= (WXFont
) 0;
151 wxWindowDC::wxWindowDC()
156 wxWindowDC::wxWindowDC( wxWindow
*window
)
158 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
163 m_font
= window
->GetFont();
166 m_display
= window
->GetXDisplay();
167 m_pixmap
= window
->GetXWindow();
168 Display
* display
= (Display
*) m_display
;
170 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
173 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
174 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
175 gcvalues
.graphics_exposures
= False
;
176 gcvalues
.subwindow_mode
= IncludeInferiors
;
177 gcvalues
.line_width
= 1;
178 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
179 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
182 if (m_window
->GetBackingPixmap())
184 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
185 DefaultScreen (display
)),
186 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
190 m_backgroundPixel
= (int) gcvalues
.background
;
192 // Get the current Font so we can set it back later
194 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
195 m_oldFont
= (WXFont
) valReturn
.font
;
197 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
200 wxWindowDC::~wxWindowDC()
202 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
204 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
206 if (m_window
&& m_window
->GetBackingPixmap())
207 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
211 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
215 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
216 m_gcBacking
= (WXGC
) 0;
219 XDestroyRegion ((Region
) m_currentRegion
);
220 m_currentRegion
= (WXRegion
) 0;
223 XDestroyRegion ((Region
) m_userRegion
);
224 m_userRegion
= (WXRegion
) 0;
227 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
228 const wxColour
& col
, int style
);
230 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
231 const wxColour
& col
, int style
)
233 return wxDoFloodFill(this, x
, y
, col
, style
);
236 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
238 // Generic (and therefore rather inefficient) method.
239 // Could be improved.
241 wxBitmap
bitmap(1, 1);
242 memdc
.SelectObject(bitmap
);
243 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
244 memdc
.SelectObject(wxNullBitmap
);
245 wxImage image
= bitmap
.ConvertToImage();
246 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
250 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
252 wxCHECK_RET( Ok(), "invalid dc" );
254 int x1d
, y1d
, x2d
, y2d
;
264 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
266 if (m_window
&& m_window
->GetBackingPixmap())
267 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
268 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
269 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
271 CalcBoundingBox(x1
, y1
);
272 CalcBoundingBox(x2
, y2
);
275 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
277 wxCHECK_RET( Ok(), "invalid dc" );
282 int xx
= XLOG2DEV (x
);
283 int yy
= YLOG2DEV (y
);
285 wxDisplaySize (&ww
, &hh
);
286 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
288 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
291 if (m_window
&& m_window
->GetBackingPixmap())
295 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
298 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
304 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
306 wxCHECK_RET( Ok(), "invalid dc" );
308 int xx1
= XLOG2DEV (x1
);
309 int yy1
= YLOG2DEV (y1
);
310 int xx2
= XLOG2DEV (x2
);
311 int yy2
= YLOG2DEV (y2
);
312 int xxc
= XLOG2DEV (xc
);
313 int yyc
= YLOG2DEV (yc
);
314 int xxc_2
= XLOG2DEV_2 (xc
);
315 int yyc_2
= YLOG2DEV_2 (yc
);
317 wxCoord dx
= xx1
- xxc
;
318 wxCoord dy
= yy1
- yyc
;
319 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
320 wxCoord r
= (wxCoord
) radius
;
322 double radius1
, radius2
;
324 if (xx1
== xx2
&& yy1
== yy2
)
329 else if (radius
== 0.0)
330 radius1
= radius2
= 0.0;
339 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
347 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
351 int alpha1
= (int) radius1
;
352 int alpha2
= (int) (radius2
- radius1
);
355 while (alpha2
> 360 * 64)
358 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
361 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
362 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
364 if (m_window
&& m_window
->GetBackingPixmap())
365 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
366 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
370 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
374 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
375 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
377 if (m_window
&& m_window
->GetBackingPixmap())
378 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
379 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
381 CalcBoundingBox (x1
, y1
);
382 CalcBoundingBox (x2
, y2
);
385 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
387 wxCHECK_RET( Ok(), "invalid dc" );
393 wd
= XLOG2DEVREL(width
);
394 hd
= YLOG2DEVREL(height
);
396 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
397 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
398 int start
= int(sa
*64);
399 int end
= int(ea
*64);
400 if (start
<0) start
+=360*64;
401 if (end
<0) end
+=360*64;
402 if (end
>start
) end
-=start
;
403 else end
+=360*64-start
;
405 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
407 m_autoSetting
= TRUE
; // must be reset
410 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
412 if (m_window
&& m_window
->GetBackingPixmap())
413 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
414 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
417 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
421 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
422 if (m_window
&& m_window
->GetBackingPixmap())
423 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
424 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
426 CalcBoundingBox (x
, y
);
427 CalcBoundingBox (x
+ width
, y
+ height
);
430 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
432 wxCHECK_RET( Ok(), "invalid dc" );
434 if (m_pen
.Ok() && m_autoSetting
)
437 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
438 if (m_window
&& m_window
->GetBackingPixmap())
439 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
441 CalcBoundingBox (x
, y
);
444 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
446 wxCHECK_RET( Ok(), "invalid dc" );
448 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
453 XPoint
*xpoints
= new XPoint
[n
];
456 for (i
= 0; i
< n
; i
++)
458 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
459 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
461 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
463 if (m_window
&& m_window
->GetBackingPixmap())
465 for (i
= 0; i
< n
; i
++)
467 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
468 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
470 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
476 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
477 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
479 wxCHECK_RET( Ok(), "invalid dc" );
481 XPoint
*xpoints1
= new XPoint
[n
+ 1];
482 XPoint
*xpoints2
= new XPoint
[n
+ 1];
484 for (i
= 0; i
< n
; i
++)
486 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
487 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
488 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
489 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
490 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
493 // Close figure for XDrawLines (not needed for XFillPolygon)
494 xpoints1
[i
].x
= xpoints1
[0].x
;
495 xpoints1
[i
].y
= xpoints1
[0].y
;
496 xpoints2
[i
].x
= xpoints2
[0].x
;
497 xpoints2
[i
].y
= xpoints2
[0].y
;
499 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
502 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
503 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
504 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
505 if (m_window
&& m_window
->GetBackingPixmap())
507 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
508 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
509 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
510 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
514 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
518 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
520 if (m_window
&& m_window
->GetBackingPixmap())
521 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
528 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
530 wxCHECK_RET( Ok(), "invalid dc" );
532 int xd
, yd
, wfd
, hfd
, wd
, hd
;
536 wfd
= XLOG2DEVREL(width
);
538 hfd
= YLOG2DEVREL(height
);
541 if (wfd
== 0 || hfd
== 0) return;
542 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
543 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
545 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
548 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
550 if (m_window
&& m_window
->GetBackingPixmap())
551 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
552 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
556 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
560 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
562 if (m_window
&& m_window
->GetBackingPixmap())
563 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
564 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
567 CalcBoundingBox (x
, y
);
568 CalcBoundingBox (x
+ width
, y
+ height
);
571 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
573 wxCHECK_RET( Ok(), "invalid dc" );
575 // If radius is negative, it's a proportion of the smaller dimension.
577 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
579 int xd
= XLOG2DEV (x
);
580 int yd
= YLOG2DEV (y
);
581 int rd
= XLOG2DEVREL ((long) radius
);
582 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
583 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
588 // If radius is zero use DrawRectangle() instead to avoid
589 // X drawing errors with small radii
592 DrawRectangle( x
, y
, width
, height
);
596 // Draw nothing if transformed w or h is 0
597 if (wd
== 0 || hd
== 0) return;
599 // CMB: adjust size if outline is drawn otherwise the result is
600 // 1 pixel too wide and high
601 if (m_pen
.GetStyle() != wxTRANSPARENT
)
607 // CMB: ensure dd is not larger than rectangle otherwise we
608 // get an hour glass shape
609 if (rw_d
> wd
) rw_d
= wd
;
610 if (rw_d
> hd
) rw_d
= hd
;
613 // For backing pixmap
614 int xd2
= XLOG2DEV_2 (x
);
615 int yd2
= YLOG2DEV_2 (y
);
616 int rd2
= XLOG2DEVREL ((long) radius
);
617 int wd2
= XLOG2DEVREL (width
) ;
618 int hd2
= YLOG2DEVREL (height
) ;
623 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
627 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
629 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
632 // Arcs start from 3 o'clock, positive angles anticlockwise
634 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
635 rw_d
, rh_d
, 90 * 64, 90 * 64);
637 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
638 // rw_d, rh_d, 0, 90 * 64);
639 rw_d
, rh_d
, 0, 91 * 64);
641 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
643 // rw_d, rh_d, 270 * 64, 90 * 64);
644 rw_d
, rh_d
, 269 * 64, 92 * 64);
646 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
647 rw_d
, rh_d
, 180 * 64, 90 * 64);
649 if (m_window
&& m_window
->GetBackingPixmap())
651 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
652 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
653 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
654 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
656 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
657 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
658 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
659 xd2
+ wd2
- rw_d2
, yd2
,
660 // rw_d2, rh_d2, 0, 90 * 64);
661 rw_d2
, rh_d2
, 0, 91 * 64);
662 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
665 // rw_d2, rh_d2, 270 * 64, 90 * 64);
666 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
667 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
668 xd2
, yd2
+ hd2
- rh_d2
,
669 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
673 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
676 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
677 xd
+ wd
- rd
+ 1, yd
);
678 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
679 xd
+ wd
- rd
, yd
+ hd
);
681 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
683 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
684 xd
+ wd
, yd
+ hd
- rd
+ 1);
685 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
686 rw_d
, rh_d
, 90 * 64, 90 * 64);
687 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
688 // rw_d, rh_d, 0, 90 * 64);
689 rw_d
, rh_d
, 0, 91 * 64);
690 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
692 rw_d
, rh_d
, 269 * 64, 92 * 64);
693 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
694 rw_d
, rh_d
, 180 * 64, 90 * 64);
696 if (m_window
&& m_window
->GetBackingPixmap())
698 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
700 xd2
+ wd2
- rd2
+ 1, yd2
);
701 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
702 xd2
+ rd2
, yd2
+ hd2
,
703 xd2
+ wd2
- rd2
, yd2
+ hd2
);
705 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
707 xd2
, yd2
+ hd2
- rd2
);
708 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
709 xd2
+ wd2
, yd2
+ rd2
,
710 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
711 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
713 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
714 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
715 xd2
+ wd2
- rw_d2
, yd2
,
716 // rw_d2, rh_d2, 0, 90 * 64);
717 rw_d2
, rh_d2
, 0, 91 * 64);
718 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
721 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
722 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
723 xd2
, yd2
+ hd2
- rh_d2
,
724 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
727 CalcBoundingBox (x
, y
);
728 CalcBoundingBox (x
+ width
, y
+ height
);
731 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
733 wxCHECK_RET( Ok(), "invalid dc" );
735 // Check for negative width and height
748 static const int angle
= 23040;
754 wd
= XLOG2DEVREL(width
) ;
755 hd
= YLOG2DEVREL(height
) ;
757 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
760 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
761 if (m_window
&& m_window
->GetBackingPixmap())
762 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
763 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
764 XLOG2DEVREL (width
) - WX_GC_CF
,
765 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
768 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
772 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
773 if (m_window
&& m_window
->GetBackingPixmap())
774 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
775 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
776 XLOG2DEVREL (width
) - WX_GC_CF
,
777 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
779 CalcBoundingBox (x
, y
);
780 CalcBoundingBox (x
+ width
, y
+ height
);
784 bool wxWindowDC::CanDrawBitmap() const
786 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
791 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
792 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
793 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
794 wxCoord xsrcMask
, wxCoord ysrcMask
)
796 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
798 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
800 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
802 // Be sure that foreground pixels (1) of the Icon will be painted with
803 // foreground colour. [m_textForegroundColour] Background pixels (0)
804 // will be painted with backgound colour (m_textBackgroundColour)
805 // Using ::SetPen is horribly slow, so avoid doing it
806 int oldBackgroundPixel
= -1;
807 int oldForegroundPixel
= -1;
809 if (m_textBackgroundColour
.Ok())
811 oldBackgroundPixel
= m_backgroundPixel
;
812 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
814 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
815 if (m_window
&& m_window
->GetBackingPixmap())
816 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
819 if (m_textForegroundColour
.Ok())
821 oldForegroundPixel
= m_currentColour
.GetPixel();
823 if( m_textForegroundColour
.GetPixel() <= -1 )
824 CalculatePixel( m_textForegroundColour
,
825 m_textForegroundColour
, TRUE
);
827 int pixel
= m_textForegroundColour
.GetPixel();
829 SetForegroundPixelWithLogicalFunction(pixel
);
832 // Do bitmap scaling if necessary
834 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
835 Pixmap sourcePixmap
= (Pixmap
) NULL
;
836 double scaleX
, scaleY
;
837 GetUserScale(& scaleX
, & scaleY
);
840 /* TODO: use the mask origin when drawing transparently */
841 if (xsrcMask
== -1 && ysrcMask
== -1)
843 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
846 // Sorry, can't scale masks just yet
847 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
849 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
850 wxBitmap
& bitmap
= memDC
->GetBitmap();
852 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
854 wxImage image
= bitmap
.ConvertToImage();
857 sourcePixmap
= (Pixmap
) bitmap
.GetDrawable();
861 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
862 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
864 image
= image
.Scale(scaledW
, scaledH
);
865 scaledBitmap
= new wxBitmap(image
);
866 sourcePixmap
= (Pixmap
) scaledBitmap
->GetDrawable();
870 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
872 if (m_pixmap
&& sourcePixmap
)
875 int orig
= m_logicalFunction
;
877 SetLogicalFunction (rop
);
879 if (m_display
!= sourceDC
->m_display
)
881 XImage
*cache
= NULL
;
883 if (m_window
&& m_window
->GetBackingPixmap())
884 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
885 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
887 source
->LogicalToDeviceX (xsrc
),
888 source
->LogicalToDeviceY (ysrc
),
889 source
->LogicalToDeviceXRel(width
),
890 source
->LogicalToDeviceYRel(height
),
891 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
894 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
896 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
897 wxBitmap
& sel
= memDC
->GetBitmap();
898 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
900 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
901 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
905 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
906 source
->LogicalToDeviceX (xsrc
),
907 source
->LogicalToDeviceY (ysrc
),
908 source
->LogicalToDeviceXRel(width
),
909 source
->LogicalToDeviceYRel(height
),
910 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
915 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
916 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
920 { //XGCValues values;
921 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
923 if (m_window
&& m_window
->GetBackingPixmap())
925 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
926 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
928 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
929 source
->LogicalToDeviceX (xsrc
),
930 source
->LogicalToDeviceY (ysrc
),
931 source
->LogicalToDeviceXRel(width
),
932 source
->LogicalToDeviceYRel(height
),
933 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
937 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
938 source
->LogicalToDeviceX (xsrc
),
939 source
->LogicalToDeviceY (ysrc
),
940 source
->LogicalToDeviceXRel(width
),
941 source
->LogicalToDeviceYRel(height
),
942 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
945 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
947 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
948 wxBitmap
& sel
= memDC
->GetBitmap();
949 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
951 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
952 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
956 // Check if we're copying from a mono bitmap
957 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
958 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
960 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
961 source
->LogicalToDeviceX (xsrc
),
962 source
->LogicalToDeviceY (ysrc
),
963 source
->LogicalToDeviceXRel(width
),
964 source
->LogicalToDeviceYRel(height
),
965 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
969 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
970 source
->LogicalToDeviceX (xsrc
),
971 source
->LogicalToDeviceY (ysrc
),
972 source
->LogicalToDeviceXRel(width
),
973 source
->LogicalToDeviceYRel(height
),
974 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
979 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
980 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
983 } /* Remote/local (Display*) m_display */
984 CalcBoundingBox (xdest
, ydest
);
985 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
987 SetLogicalFunction(orig
);
991 if (scaledBitmap
) delete scaledBitmap
;
993 if (oldBackgroundPixel
> -1)
995 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
996 if (m_window
&& m_window
->GetBackingPixmap())
997 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1000 if (oldForegroundPixel
> -1)
1002 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1003 if (m_window
&& m_window
->GetBackingPixmap())
1004 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1005 oldForegroundPixel
);
1011 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1013 wxCHECK_RET( Ok(), "invalid dc" );
1015 // Since X draws from the baseline of the text, must add the text height
1021 // Set FillStyle, otherwise X will use current stipple!
1022 XGCValues gcV
, gcBackingV
;
1024 XGetGCValues ((Display
*) m_display
, (GC
)m_gc
, GCFillStyle
, &gcV
);
1025 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1026 if (m_window
&& m_window
->GetBackingPixmap())
1028 XGetGCValues ((Display
*) m_display
, (GC
)m_gcBacking
, GCFillStyle
,
1030 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
, FillSolid
);
1033 slen
= strlen(text
);
1037 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1038 int direction
, descent
;
1039 XCharStruct overall_return
;
1042 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1043 &ascent
, &descent
, &overall_return
);
1046 (void)XTextExtents((XFontStruct
*) pFontStruct
,
1047 wxConstCast(text
.c_str(), char),
1049 &ascent
, &descent
, &overall_return
);
1051 cx
= overall_return
.width
;
1052 cy
= ascent
+ descent
;
1055 // First draw a rectangle representing the text background, if a text
1056 // background is specified
1057 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1059 wxColour oldPenColour
= m_currentColour
;
1060 m_currentColour
= m_textBackgroundColour
;
1061 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1062 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1063 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1064 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1066 // This separation of the big && test required for gcc2.7/HP UX 9.02
1067 // or pixel value can be corrupted!
1068 sameColour
= (sameColour
&&
1069 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1071 if (!sameColour
|| !GetOptimization())
1073 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1074 m_currentColour
= m_textBackgroundColour
;
1076 // Set the GC to the required colour
1079 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1080 if (m_window
&& m_window
->GetBackingPixmap())
1081 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1085 m_textBackgroundColour
= oldPenColour
;
1087 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1088 if (m_window
&& m_window
->GetBackingPixmap())
1089 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1090 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1093 // Now set the text foreground and draw the text
1094 if (m_textForegroundColour
.Ok ())
1096 wxColour oldPenColour
= m_currentColour
;
1097 m_currentColour
= m_textForegroundColour
;
1098 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1099 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1100 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1101 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1102 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1104 if (!sameColour
|| !GetOptimization())
1106 int pixel
= CalculatePixel(m_textForegroundColour
,
1107 m_currentColour
, FALSE
);
1109 // Set the GC to the required colour
1112 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1113 if (m_window
&& m_window
->GetBackingPixmap())
1114 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1118 m_textForegroundColour
= oldPenColour
;
1121 // We need to add the ascent, not the whole height, since X draws at the
1122 // point above the descender.
1125 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1126 (XChar2b
*)(char*) (const char*) text
, slen
);
1129 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1131 if (m_window
&& m_window
->GetBackingPixmap()) {
1134 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1135 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1136 (XChar2b
*)(char*) (const char*) text
, slen
);
1139 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1140 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1141 wxConstCast(text
.c_str(), char), slen
);
1144 // restore fill style
1145 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, gcV
.fill_style
);
1146 if (m_window
&& m_window
->GetBackingPixmap())
1147 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
,
1148 gcBackingV
.fill_style
);
1151 GetTextExtent (text
, &w
, &h
);
1152 CalcBoundingBox (x
+ w
, y
+ h
);
1153 CalcBoundingBox (x
, y
);
1156 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
,
1161 DrawText(text
, x
, y
);
1165 wxCHECK_RET( Ok(), "invalid dc" );
1167 int oldBackgroundPixel
= -1;
1168 int oldForegroundPixel
= -1;
1169 int foregroundPixel
= -1;
1170 int backgroundPixel
= -1;
1172 if (m_textBackgroundColour
.Ok())
1174 oldBackgroundPixel
= m_backgroundPixel
;
1175 backgroundPixel
= m_textBackgroundColour
.AllocColour(m_display
);
1177 if (m_textForegroundColour
.Ok())
1179 oldForegroundPixel
= m_currentColour
.GetPixel();
1181 if( m_textForegroundColour
.GetPixel() <= -1 )
1182 CalculatePixel( m_textForegroundColour
,
1183 m_textForegroundColour
, TRUE
);
1185 foregroundPixel
= m_textForegroundColour
.GetPixel();
1188 // Since X draws from the baseline of the text, must add the text height
1192 int slen
= text
.length();
1196 // Calculate text extent.
1197 WXFontStructPtr pFontStruct
=
1198 m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1199 int direction
, descent
;
1200 XCharStruct overall_return
;
1203 (void)XTextExtents16((XFontStruct
*) pFontStruct
,
1204 (XChar2b
*)(const char*) text
,
1206 &ascent
, &descent
, &overall_return
);
1209 (void)XTextExtents((XFontStruct
*) pFontStruct
,
1210 wxConstCast(text
.c_str(), char),
1212 &ascent
, &descent
, &overall_return
);
1214 cx
= overall_return
.width
;
1215 cy
= ascent
+ descent
;
1218 wxBitmap
src(cx
, cy
);
1220 dc
.SelectObject(src
);
1221 dc
.SetFont(GetFont());
1222 dc
.SetBackground(*wxWHITE_BRUSH
);
1223 dc
.SetBrush(*wxBLACK_BRUSH
);
1225 dc
.DrawText(text
, 0, 0);
1226 dc
.SetFont(wxNullFont
);
1228 // Calculate the size of the rotated bounding box.
1229 double dx
= cos(angle
/ 180.0 * M_PI
);
1230 double dy
= sin(angle
/ 180.0 * M_PI
);
1231 double x4
= cy
* dy
;
1232 double y4
= cy
* dx
;
1233 double x3
= cx
* dx
;
1234 double y3
= -cx
* dy
;
1235 double x2
= x3
+ x4
;
1236 double y2
= y3
+ y4
;
1240 // Create image from the source bitmap after writing the text into it.
1241 wxImage image
= src
.ConvertToImage();
1243 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1244 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1245 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1246 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1248 bool lastFore
= false, lastBack
= false;
1250 // This rotates counterclockwise around the top left corner.
1251 for (int rx
= minx
; rx
< maxx
; rx
++)
1253 for (int ry
= miny
; ry
< maxy
; ry
++)
1255 // transform dest coords to source coords
1256 int sx
= (int) (rx
* dx
- ry
* dy
+ 0.5);
1257 int sy
= - (int) (-ry
* dx
- rx
* dy
+ 0.5);
1258 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1260 bool textPixel
= image
.GetRed(sx
, sy
) == 0;
1262 if (!textPixel
&& m_backgroundMode
!= wxSOLID
)
1265 wxCoord ox
= (wxCoord
) (x1
+ rx
),
1266 oy
= (wxCoord
) (y1
+ ry
);
1267 // draw black pixels, ignore white ones (i.e. transparent b/g)
1268 if (textPixel
&& !lastFore
)
1270 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1275 else if (!textPixel
&& !lastBack
)
1277 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1283 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
,
1284 (GC
) m_gc
, XLOG2DEV (ox
), YLOG2DEV (oy
));
1285 if (m_window
&& m_window
->GetBackingPixmap())
1286 XDrawPoint ((Display
*) m_display
,
1287 (Pixmap
) m_window
->GetBackingPixmap(),
1289 XLOG2DEV_2 (ox
), YLOG2DEV_2 (oy
));
1294 if (oldBackgroundPixel
> -1)
1296 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1297 if (m_window
&& m_window
->GetBackingPixmap())
1298 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1299 oldBackgroundPixel
);
1301 if (oldForegroundPixel
> -1)
1303 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1304 if (m_window
&& m_window
->GetBackingPixmap())
1305 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1306 oldForegroundPixel
);
1309 CalcBoundingBox (minx
, miny
);
1310 CalcBoundingBox (maxx
, maxy
);
1313 bool wxWindowDC::CanGetTextExtent() const
1318 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1319 wxCoord
*descent
, wxCoord
*externalLeading
,
1320 wxFont
*font
) const
1322 wxCHECK_RET( Ok(), "invalid dc" );
1324 wxFont
* theFont
= font
;
1326 theFont
= (wxFont
*)&m_font
; // const_cast
1330 // TODO: this should be an error log function
1331 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1333 if (width
) *width
= -1;
1334 if (height
) *height
= -1;
1338 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1340 int direction
, ascent
, descent2
;
1341 XCharStruct overall
;
1346 slen
= str16len(string
);
1349 slen
= strlen(string
);
1353 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1354 &ascent
, &descent2
, &overall
);
1357 XTextExtents((XFontStruct
*) pFontStruct
,
1358 wxConstCast(string
.c_str(), char), slen
, &direction
,
1359 &ascent
, &descent2
, &overall
);
1361 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1362 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1364 *descent
= descent2
;
1365 if (externalLeading
)
1366 *externalLeading
= 0;
1369 wxCoord
wxWindowDC::GetCharWidth() const
1371 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1372 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1374 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1376 int direction
, ascent
, descent
;
1377 XCharStruct overall
;
1378 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1379 &descent
, &overall
);
1380 return XDEV2LOGREL(overall
.width
);
1383 wxCoord
wxWindowDC::GetCharHeight() const
1385 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1386 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1388 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1390 int direction
, ascent
, descent
;
1391 XCharStruct overall
;
1392 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1393 &descent
, &overall
);
1394 // return XDEV2LOGREL(overall.ascent + overall.descent);
1395 return XDEV2LOGREL(ascent
+ descent
);
1398 void wxWindowDC::DoGetSize( int *width
, int *height
) const
1404 if( m_window
->GetBackingPixmap() )
1406 w
= m_window
->GetPixmapWidth();
1407 h
= m_window
->GetPixmapHeight();
1410 m_window
->GetSize( &w
, &h
);
1413 if( width
) *width
= w
;
1414 if( height
) *height
= h
;
1417 void wxWindowDC::Clear()
1419 wxCHECK_RET( Ok(), "invalid dc" );
1421 wxRect
rect( wxPoint( 0, 0 ), GetSize() );
1425 void wxWindowDC::Clear(const wxRect
& rect
)
1427 wxCHECK_RET( Ok(), "invalid dc" );
1429 int x
= rect
.x
; int y
= rect
.y
;
1430 int w
= rect
.width
; int h
= rect
.height
;
1432 wxBrush saveBrush
= m_brush
;
1433 SetBrush (m_backgroundBrush
);
1435 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1438 if (m_window
&& m_window
->GetBackingPixmap())
1439 XFillRectangle ((Display
*) m_display
,
1440 (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1443 m_brush
= saveBrush
;
1446 void wxWindowDC::SetFont( const wxFont
&font
)
1448 wxCHECK_RET( Ok(), "invalid dc" );
1454 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1456 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1458 if (m_window
&& m_window
->GetBackingPixmap())
1459 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1464 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1466 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1467 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1469 if (m_window
&& m_window
->GetBackingPixmap())
1470 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1473 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel
)
1475 if (m_logicalFunction
== wxXOR
)
1478 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1479 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1480 pixel
^ values
.background
);
1481 if (m_window
&& m_window
->GetBackingPixmap())
1482 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1483 pixel
^ values
.background
);
1487 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1488 if (m_window
&& m_window
->GetBackingPixmap())
1489 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1493 int wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1494 bool roundToWhite
) const
1496 const unsigned char wp
= (unsigned char)255;
1499 if(!m_colour
) // Mono display
1501 unsigned char red
= colour
.Red ();
1502 unsigned char blue
= colour
.Blue ();
1503 unsigned char green
= colour
.Green ();
1505 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1506 // not black and roundToWhite was specified
1507 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1510 pixel
= (int)WhitePixel((Display
*) m_display
,
1511 DefaultScreen((Display
*) m_display
));
1512 curCol
.SetPixel(pixel
);
1513 colour
.SetPixel(pixel
);
1518 pixel
= (int)BlackPixel((Display
*) m_display
,
1519 DefaultScreen((Display
*) m_display
));
1520 curCol
.SetPixel(pixel
);
1521 colour
.SetPixel(pixel
);
1527 pixel
= colour
.AllocColour((Display
*) m_display
);
1528 curCol
.SetPixel(pixel
);
1534 void wxWindowDC::SetPen( const wxPen
&pen
)
1536 wxCHECK_RET( Ok(), "invalid dc" );
1542 wxBitmap oldStipple
= m_currentStipple
;
1543 int oldStyle
= m_currentStyle
;
1544 int oldFill
= m_currentFill
;
1545 int old_pen_width
= m_currentPenWidth
;
1546 int old_pen_join
= m_currentPenJoin
;
1547 int old_pen_cap
= m_currentPenCap
;
1548 int old_pen_nb_dash
= m_currentPenDashCount
;
1549 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1551 wxColour oldPenColour
= m_currentColour
;
1552 m_currentColour
= m_pen
.GetColour ();
1553 m_currentStyle
= m_pen
.GetStyle ();
1554 m_currentFill
= m_pen
.GetStyle (); // TODO?
1555 m_currentPenWidth
= m_pen
.GetWidth ();
1556 m_currentPenJoin
= m_pen
.GetJoin ();
1557 m_currentPenCap
= m_pen
.GetCap ();
1558 m_currentPenDashCount
= m_pen
.GetDashCount();
1559 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1561 if (m_currentStyle
== wxSTIPPLE
)
1562 m_currentStipple
= * m_pen
.GetStipple ();
1564 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1565 oldFill
== m_currentFill
&&
1566 old_pen_join
== m_currentPenJoin
&&
1567 old_pen_cap
== m_currentPenCap
&&
1568 old_pen_nb_dash
== m_currentPenDashCount
&&
1569 old_pen_dash
== m_currentPenDash
&&
1570 old_pen_width
== m_currentPenWidth
);
1572 bool sameColour
= (oldPenColour
.Ok () &&
1573 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1574 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1575 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1576 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1578 if (!sameStyle
|| !GetOptimization())
1580 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1581 if (scaled_width
< 0)
1587 static const wxX11Dash dotted
[] = {2, 5};
1588 static const wxX11Dash short_dashed
[] = {4, 4};
1589 static const wxX11Dash long_dashed
[] = {4, 8};
1590 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1592 // We express dash pattern in pen width unit, so we are
1593 // independent of zoom factor and so on...
1595 const wxX11Dash
*req_dash
;
1597 switch (m_pen
.GetStyle ())
1600 req_nb_dash
= m_currentPenDashCount
;
1601 req_dash
= m_currentPenDash
;
1602 style
= LineOnOffDash
;
1607 style
= LineOnOffDash
;
1611 req_dash
= short_dashed
;
1612 style
= LineOnOffDash
;
1616 req_dash
= long_dashed
;
1617 style
= LineOnOffDash
;
1621 req_dash
= dotted_dashed
;
1622 style
= LineOnOffDash
;
1629 req_dash
= (wxX11Dash
*)NULL
;
1633 if (req_dash
&& req_nb_dash
)
1635 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1638 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1639 for (int i
= 0; i
< req_nb_dash
; i
++)
1640 real_req_dash
[i
] = req_dash
[i
] * factor
;
1641 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1643 if (m_window
&& m_window
->GetBackingPixmap())
1644 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1645 delete[]real_req_dash
;
1649 // No Memory. We use non-scaled dash pattern...
1650 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1652 if (m_window
&& m_window
->GetBackingPixmap())
1653 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1657 switch (m_pen
.GetCap ())
1659 case wxCAP_PROJECTING
:
1660 cap
= CapProjecting
;
1667 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1671 switch (m_pen
.GetJoin ())
1685 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1687 if (m_window
&& m_window
->GetBackingPixmap())
1688 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1691 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1695 oldStipple
= wxNullBitmap
; // For later reset!!
1697 switch (m_currentFill
)
1699 case wxBDIAGONAL_HATCH
:
1700 if (bdiag
== (Pixmap
) 0)
1701 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1702 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1703 bdiag_bits
, bdiag_width
, bdiag_height
);
1706 case wxFDIAGONAL_HATCH
:
1707 if (fdiag
== (Pixmap
) 0)
1708 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1709 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1710 fdiag_bits
, fdiag_width
, fdiag_height
);
1714 if (cross
== (Pixmap
) 0)
1715 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1716 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1717 cross_bits
, cross_width
, cross_height
);
1720 case wxHORIZONTAL_HATCH
:
1721 if (horiz
== (Pixmap
) 0)
1722 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1723 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1724 horiz_bits
, horiz_width
, horiz_height
);
1727 case wxVERTICAL_HATCH
:
1728 if (verti
== (Pixmap
) 0)
1729 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1730 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1731 verti_bits
, verti_width
, verti_height
);
1734 case wxCROSSDIAG_HATCH
:
1736 if (cdiag
== (Pixmap
) 0)
1737 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1738 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1739 cdiag_bits
, cdiag_width
, cdiag_height
);
1743 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1745 if (m_window
&& m_window
->GetBackingPixmap())
1746 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1748 else if (m_currentStipple
.Ok()
1749 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1751 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetDrawable());
1753 if (m_window
&& m_window
->GetBackingPixmap())
1754 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetDrawable());
1757 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1761 if (m_currentFill
== wxSTIPPLE
)
1762 fill_style
= FillStippled
;
1763 else if (IS_HATCH (m_currentFill
))
1764 fill_style
= FillStippled
;
1766 fill_style
= FillSolid
;
1767 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1768 if (m_window
&& m_window
->GetBackingPixmap())
1769 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1772 // must test m_logicalFunction, because it involves background!
1773 if (!sameColour
|| !GetOptimization()
1774 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1777 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1778 pixel
= m_backgroundPixel
;
1781 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, FALSE
);
1784 // Finally, set the GC to the required colour
1786 SetForegroundPixelWithLogicalFunction(pixel
);
1789 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1794 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1796 wxCHECK_RET( Ok(), "invalid dc" );
1800 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1803 int oldFill
= m_currentFill
;
1804 wxBitmap oldStipple
= m_currentStipple
;
1806 m_autoSetting
|= 0x1;
1808 m_currentFill
= m_brush
.GetStyle ();
1809 if (m_currentFill
== wxSTIPPLE
)
1810 m_currentStipple
= * m_brush
.GetStipple ();
1812 wxColour
oldBrushColour(m_currentColour
);
1813 m_currentColour
= m_brush
.GetColour ();
1815 bool sameColour
= (oldBrushColour
.Ok () &&
1816 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1817 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1818 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1819 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1821 int stippleDepth
= -1;
1823 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1825 switch (brush
.GetStyle ())
1830 stippleDepth
= m_currentStipple
.GetDepth();
1832 case wxBDIAGONAL_HATCH
:
1833 case wxCROSSDIAG_HATCH
:
1834 case wxFDIAGONAL_HATCH
:
1836 case wxHORIZONTAL_HATCH
:
1837 case wxVERTICAL_HATCH
:
1839 if (stippleDepth
== -1) stippleDepth
= 1;
1841 // Chris Breeze 23/07/97: use background mode to
1842 // determine whether fill style should be solid or
1844 int style
= stippleDepth
== 1 ?
1845 (m_backgroundMode
== wxSOLID
?
1846 FillOpaqueStippled
: FillStippled
) :
1848 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1849 if (m_window
&& m_window
->GetBackingPixmap())
1850 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1855 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1856 if (m_window
&& m_window
->GetBackingPixmap())
1857 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
,
1862 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1866 switch (m_currentFill
)
1868 case wxBDIAGONAL_HATCH
:
1869 if (bdiag
== (Pixmap
) 0)
1870 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1871 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1872 bdiag_bits
, bdiag_width
, bdiag_height
);
1875 case wxFDIAGONAL_HATCH
:
1876 if (fdiag
== (Pixmap
) 0)
1877 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1878 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1879 fdiag_bits
, fdiag_width
, fdiag_height
);
1883 if (cross
== (Pixmap
) 0)
1884 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1885 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1886 cross_bits
, cross_width
, cross_height
);
1889 case wxHORIZONTAL_HATCH
:
1890 if (horiz
== (Pixmap
) 0)
1891 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1892 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1893 horiz_bits
, horiz_width
, horiz_height
);
1896 case wxVERTICAL_HATCH
:
1897 if (verti
== (Pixmap
) 0)
1898 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1899 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1900 verti_bits
, verti_width
, verti_height
);
1903 case wxCROSSDIAG_HATCH
:
1905 if (cdiag
== (Pixmap
) 0)
1906 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1907 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1908 cdiag_bits
, cdiag_width
, cdiag_height
);
1912 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1914 if (m_window
&& m_window
->GetBackingPixmap())
1915 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1917 // X can forget the stipple value when resizing a window (apparently)
1918 // so always set the stipple.
1919 else if (m_currentFill
!= wxSOLID
&& m_currentFill
!= wxTRANSPARENT
&&
1920 m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1922 if (m_currentStipple
.GetDepth() == 1)
1924 XSetStipple ((Display
*) m_display
, (GC
) m_gc
,
1925 (Pixmap
) m_currentStipple
.GetDrawable());
1926 if (m_window
&& m_window
->GetBackingPixmap())
1927 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
,
1928 (Pixmap
) m_currentStipple
.GetDrawable());
1932 XSetTile ((Display
*) m_display
, (GC
) m_gc
,
1933 (Pixmap
) m_currentStipple
.GetDrawable());
1934 if (m_window
&& m_window
->GetBackingPixmap())
1935 XSetTile ((Display
*) m_display
,(GC
) m_gcBacking
,
1936 (Pixmap
) m_currentStipple
.GetDrawable());
1940 // must test m_logicalFunction, because it involves background!
1941 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1943 int pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, TRUE
);
1946 SetForegroundPixelWithLogicalFunction(pixel
);
1949 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1952 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1954 wxCHECK_RET( Ok(), "invalid dc" );
1956 m_backgroundBrush
= brush
;
1958 if (!m_backgroundBrush
.Ok())
1961 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1963 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1964 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1965 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
1966 if (m_window
&& m_window
->GetBackingPixmap())
1967 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1971 void wxWindowDC::SetLogicalFunction( int function
)
1973 wxCHECK_RET( Ok(), "invalid dc" );
1978 if (m_logicalFunction
== function
)
1984 x_function
= GXclear
;
1990 x_function
= GXinvert
;
1993 x_function
= GXorReverse
;
1996 x_function
= GXandReverse
;
2005 x_function
= GXandInverted
;
2008 x_function
= GXnoop
;
2014 x_function
= GXequiv
;
2017 x_function
= GXcopyInverted
;
2020 x_function
= GXorInverted
;
2023 x_function
= GXnand
;
2030 x_function
= GXcopy
;
2034 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2035 if (m_window
&& m_window
->GetBackingPixmap())
2036 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2038 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2039 /* MATTHEW: [9] Need to redo pen simply */
2040 m_autoSetting
|= 0x2;
2042 m_logicalFunction
= function
;
2046 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2048 wxCHECK_RET( Ok(), "invalid dc" );
2050 m_textForegroundColour
= col
;
2053 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2055 wxCHECK_RET( Ok(), "invalid dc" );
2057 m_textBackgroundColour
= col
;
2060 void wxWindowDC::SetBackgroundMode( int mode
)
2062 m_backgroundMode
= mode
;
2065 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2070 /* Use GetXColormap */
2071 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2072 (Colormap
) palette
.GetXColormap());
2074 /* Use wxGetMainColormap */
2075 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2076 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2081 void wxWindowDC::SetDCClipping()
2083 // m_userRegion is the region set by calling SetClippingRegion
2085 if (m_currentRegion
)
2086 XDestroyRegion ((Region
) m_currentRegion
);
2088 // We need to take into account
2089 // clipping imposed on a window by a repaint.
2090 // We'll combine it with the user region. But for now,
2091 // just use the currently-defined user clipping region.
2092 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2093 m_currentRegion
= (WXRegion
) XCreateRegion ();
2095 m_currentRegion
= (WXRegion
) NULL
;
2097 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2098 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2099 else if (m_userRegion
)
2100 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2101 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2102 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2103 (Region
) m_currentRegion
);
2105 if (m_currentRegion
)
2107 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2111 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2116 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2118 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2121 XDestroyRegion ((Region
) m_userRegion
);
2122 m_userRegion
= (WXRegion
) XCreateRegion ();
2126 r
.width
= XLOG2DEVREL(width
);
2127 r
.height
= YLOG2DEVREL(height
);
2128 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2132 // Needs to work differently for Pixmap: without this,
2133 // there's a nasty (Display*) m_display bug. 8/12/94
2134 if (m_window
&& m_window
->GetBackingPixmap())
2136 XRectangle rects
[1];
2137 rects
[0].x
= XLOG2DEV_2(x
);
2138 rects
[0].y
= YLOG2DEV_2(y
);
2139 rects
[0].width
= XLOG2DEVREL(width
);
2140 rects
[0].height
= YLOG2DEVREL(height
);
2141 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2145 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2147 wxRect box
= region
.GetBox();
2149 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2152 XDestroyRegion ((Region
) m_userRegion
);
2153 m_userRegion
= (WXRegion
) XCreateRegion ();
2155 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2159 // Needs to work differently for Pixmap: without this,
2160 // there's a nasty (Display*) m_display bug. 8/12/94
2161 if (m_window
&& m_window
->GetBackingPixmap())
2163 XRectangle rects
[1];
2164 rects
[0].x
= XLOG2DEV_2(box
.x
);
2165 rects
[0].y
= YLOG2DEV_2(box
.y
);
2166 rects
[0].width
= XLOG2DEVREL(box
.width
);
2167 rects
[0].height
= YLOG2DEVREL(box
.height
);
2168 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2173 void wxWindowDC::DestroyClippingRegion()
2175 wxDC::DestroyClippingRegion();
2178 XDestroyRegion ((Region
) m_userRegion
);
2179 m_userRegion
= NULL
;
2184 gc_val
.clip_mask
= None
;
2185 if (m_window
&& m_window
->GetBackingPixmap())
2186 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2189 // Resolution in pixels per logical inch
2190 wxSize
wxWindowDC::GetPPI() const
2192 return wxSize(100, 100);
2195 int wxWindowDC::GetDepth() const
2204 // ----------------------------------------------------------------------------
2206 // ----------------------------------------------------------------------------
2208 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2210 wxRegion
* region
= NULL
;
2212 // Combine all the update rects into a region
2213 const wxRectList
& updateRects(win
->GetUpdateRects());
2214 if ( updateRects
.GetCount() != 0 )
2216 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2218 node
= node
->GetNext() )
2220 wxRect
* rect
= node
->GetData();
2223 region
= new wxRegion(*rect
);
2225 // TODO: is this correct? In SetDCClipping above,
2226 // XIntersectRegion is used to combine paint and user
2227 // regions. XIntersectRegion appears to work in that case...
2228 region
->Union(*rect
);
2234 win
->GetClientSize(&cw
, &ch
);
2235 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2238 win
->SetUpdateRegion(*region
);
2240 wxRegion
& theRegion(win
->GetUpdateRegion());
2241 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2243 // Set the clipping region. Any user-defined region will be combined with this
2244 // one in SetDCClipping.
2245 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2250 wxPaintDC::~wxPaintDC()
2252 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2254 m_window
->ClearUpdateRegion();
2257 // ----------------------------------------------------------------------------
2258 // private functions
2259 // ----------------------------------------------------------------------------
2262 Used when copying between drawables on different (Display*) m_displays. Not
2263 very fast, but better than giving up.
2266 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2267 Drawable src
, Drawable dest
,
2270 unsigned int w
, unsigned int h
,
2271 int destx
, int desty
,
2272 bool more
, XImage
**cache
)
2274 XImage
*image
, *destimage
;
2275 Colormap destcm
, srccm
;
2276 static const int CACHE_SIZE
= 256;
2279 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2280 int k
, cache_pos
, all_cache
;
2282 if (!cache
|| !*cache
)
2283 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2287 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2289 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2290 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2295 for (i
= 0; i
< w
; i
++)
2296 for (j
= 0; j
< h
; j
++) {
2297 unsigned long pixel
;
2300 pixel
= XGetPixel(image
, i
, j
);
2301 for (k
= cache_pos
; k
--; )
2302 if (cachesrc
[k
] == pixel
) {
2303 pixel
= cachedest
[k
];
2307 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2308 if (cachesrc
[k
] == pixel
) {
2309 pixel
= cachedest
[k
];
2313 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2314 XQueryColor(src_display
, srccm
, &xcol
);
2315 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2317 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2319 if (++cache_pos
>= CACHE_SIZE
) {
2325 XPutPixel(destimage
, i
, j
, pixel
);
2328 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2329 XDestroyImage(destimage
);
2334 XDestroyImage(image
);
2339 /* Helper function for 16-bit fonts */
2340 static int str16len(const char *s
)
2344 while (s
[0] && s
[1]) {