1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 About pens, brushes, and the autoSetting flag:
15 Under X, pens and brushes control some of the same X drawing
16 parameters. Therefore, it is impossible to independently maintain
17 the current pen and the current brush. Also, some settings depend on
18 the current logical function. The m_currentFill, etc. instance
19 variables remember state across the brush and pen.
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
31 // ============================================================================
33 // ============================================================================
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
39 // For compilers that support precompilation, includes "wx.h".
40 #include "wx/wxprec.h"
42 #include "wx/dcclient.h"
43 #include "wx/dcmemory.h"
44 #include "wx/window.h"
51 #pragma message disable nosimpint
55 #pragma message enable nosimpint
58 #include "wx/motif/private.h"
61 #include <float.h> // for M_PI
71 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 // Fudge factor (VZ: what??)
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
84 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
85 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
86 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
89 // IS_HATCH exists for WXWIN_COMPATIBILITY_2_4 only
90 // but wxMotif needs it for its internals here
91 #define IS_HATCH(s) ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH)
94 // FIXME: left over after removal of wxDC::GetOptimization()
95 #define GET_OPTIMIZATION false
97 // ----------------------------------------------------------------------------
99 // ----------------------------------------------------------------------------
101 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
102 Drawable src
, Drawable dest
,
105 unsigned int w
, unsigned int h
,
106 int destx
, int desty
,
107 bool more
, XImage
**cache
);
109 // ============================================================================
111 // ============================================================================
114 * compare two doubles and return the larger rounded
117 static int roundmax(double a
, double b
)
119 return (int)((a
> b
? a
: b
) + 0.5);
123 * compare two doubles and return the smaller rounded
126 static int roundmin(double a
, double b
)
128 return (int)((a
< b
? a
: b
) - 0.5);
132 // ----------------------------------------------------------------------------
134 // ----------------------------------------------------------------------------
136 void wxWindowDC::Init()
139 m_gcBacking
= (WXGC
) 0;
141 m_backgroundPixel
= -1;
142 m_currentPenWidth
= 1;
143 m_currentPenJoin
= -1;
144 m_currentPenDashCount
= -1;
145 m_currentPenDash
= (wxX11Dash
*) NULL
;
148 m_colour
= wxColourDisplay();
149 m_display
= (WXDisplay
*) NULL
;
150 m_pixmap
= (WXPixmap
) 0;
153 m_clipRegion
= (WXRegion
) 0;
156 wxWindowDC::wxWindowDC()
161 wxWindowDC::wxWindowDC( wxWindow
*window
)
163 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
168 m_font
= window
->GetFont();
171 m_display
= window
->GetXDisplay();
172 m_pixmap
= window
->GetXWindow();
173 Display
* display
= (Display
*) m_display
;
175 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
178 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
179 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
180 gcvalues
.graphics_exposures
= False
;
181 gcvalues
.subwindow_mode
= IncludeInferiors
;
182 gcvalues
.line_width
= 1;
183 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
184 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
187 if (m_window
->GetBackingPixmap())
189 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
190 DefaultScreen (display
)),
191 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
195 m_backgroundPixel
= (int) gcvalues
.background
;
197 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
200 wxWindowDC::~wxWindowDC()
203 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
207 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
208 m_gcBacking
= (WXGC
) 0;
211 XDestroyRegion ((Region
) m_clipRegion
);
212 m_clipRegion
= (WXRegion
) 0;
215 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
216 const wxColour
& col
, int style
);
218 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
219 const wxColour
& col
, int style
)
221 return wxDoFloodFill(this, x
, y
, col
, style
);
224 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
226 // Generic (and therefore rather inefficient) method.
227 // Could be improved.
229 wxBitmap
bitmap(1, 1);
230 memdc
.SelectObject(bitmap
);
231 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
232 memdc
.SelectObject(wxNullBitmap
);
233 wxImage image
= bitmap
.ConvertToImage();
234 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
238 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
240 wxCHECK_RET( Ok(), "invalid dc" );
242 int x1d
, y1d
, x2d
, y2d
;
252 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
254 if (m_window
&& m_window
->GetBackingPixmap())
255 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
256 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
257 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
259 CalcBoundingBox(x1
, y1
);
260 CalcBoundingBox(x2
, y2
);
263 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
265 wxCHECK_RET( Ok(), "invalid dc" );
270 int xx
= XLOG2DEV (x
);
271 int yy
= YLOG2DEV (y
);
273 wxDisplaySize (&ww
, &hh
);
274 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
276 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
279 if (m_window
&& m_window
->GetBackingPixmap())
283 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
286 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
292 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
294 wxCHECK_RET( Ok(), "invalid dc" );
296 int xx1
= XLOG2DEV (x1
);
297 int yy1
= YLOG2DEV (y1
);
298 int xx2
= XLOG2DEV (x2
);
299 int yy2
= YLOG2DEV (y2
);
300 int xxc
= XLOG2DEV (xc
);
301 int yyc
= YLOG2DEV (yc
);
302 int xxc_2
= XLOG2DEV_2 (xc
);
303 int yyc_2
= YLOG2DEV_2 (yc
);
305 wxCoord dx
= xx1
- xxc
;
306 wxCoord dy
= yy1
- yyc
;
307 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
308 wxCoord r
= (wxCoord
) radius
;
310 double radius1
, radius2
;
312 if (xx1
== xx2
&& yy1
== yy2
)
317 else if (radius
== 0.0)
318 radius1
= radius2
= 0.0;
327 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
335 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
339 int alpha1
= (int) radius1
;
340 int alpha2
= (int) (radius2
- radius1
);
343 while (alpha2
> 360 * 64)
346 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
349 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
350 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
352 if (m_window
&& m_window
->GetBackingPixmap())
353 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
354 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
358 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
362 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
363 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
365 if (m_window
&& m_window
->GetBackingPixmap())
366 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
367 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
369 CalcBoundingBox (x1
, y1
);
370 CalcBoundingBox (x2
, y2
);
373 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
375 wxCHECK_RET( Ok(), "invalid dc" );
381 wd
= XLOG2DEVREL(width
);
382 hd
= YLOG2DEVREL(height
);
384 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
385 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
386 int start
= int(sa
*64);
387 int end
= int(ea
*64);
388 if (start
<0) start
+=360*64;
389 if (end
<0) end
+=360*64;
390 if (end
>start
) end
-=start
;
391 else end
+=360*64-start
;
393 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
395 m_autoSetting
= true; // must be reset
398 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
400 if (m_window
&& m_window
->GetBackingPixmap())
401 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
402 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
405 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
409 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
410 if (m_window
&& m_window
->GetBackingPixmap())
411 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
412 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
414 CalcBoundingBox (x
, y
);
415 CalcBoundingBox (x
+ width
, y
+ height
);
418 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
420 wxCHECK_RET( Ok(), "invalid dc" );
422 if (m_pen
.Ok() && m_autoSetting
)
425 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
426 if (m_window
&& m_window
->GetBackingPixmap())
427 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
429 CalcBoundingBox (x
, y
);
432 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
434 wxCHECK_RET( Ok(), "invalid dc" );
436 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
441 XPoint
*xpoints
= new XPoint
[n
];
444 for (i
= 0; i
< n
; i
++)
446 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
447 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
449 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
451 if (m_window
&& m_window
->GetBackingPixmap())
453 for (i
= 0; i
< n
; i
++)
455 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
456 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
458 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
464 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
465 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
467 wxCHECK_RET( Ok(), "invalid dc" );
469 XPoint
*xpoints1
= new XPoint
[n
+ 1];
470 XPoint
*xpoints2
= new XPoint
[n
+ 1];
472 for (i
= 0; i
< n
; i
++)
474 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
475 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
476 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
477 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
478 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
481 // Close figure for XDrawLines (not needed for XFillPolygon)
482 xpoints1
[i
].x
= xpoints1
[0].x
;
483 xpoints1
[i
].y
= xpoints1
[0].y
;
484 xpoints2
[i
].x
= xpoints2
[0].x
;
485 xpoints2
[i
].y
= xpoints2
[0].y
;
487 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
490 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
491 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
492 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
493 if (m_window
&& m_window
->GetBackingPixmap())
495 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
496 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
497 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
498 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
502 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
506 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
508 if (m_window
&& m_window
->GetBackingPixmap())
509 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
516 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
518 wxCHECK_RET( Ok(), "invalid dc" );
520 int xd
, yd
, wfd
, hfd
, wd
, hd
;
524 wfd
= XLOG2DEVREL(width
);
526 hfd
= YLOG2DEVREL(height
);
529 if (wfd
== 0 || hfd
== 0) return;
530 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
531 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
533 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
536 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
538 if (m_window
&& m_window
->GetBackingPixmap())
539 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
540 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
544 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
548 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
550 if (m_window
&& m_window
->GetBackingPixmap())
551 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
552 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
555 CalcBoundingBox (x
, y
);
556 CalcBoundingBox (x
+ width
, y
+ height
);
559 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
561 wxCHECK_RET( Ok(), "invalid dc" );
563 // If radius is negative, it's a proportion of the smaller dimension.
565 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
567 int xd
= XLOG2DEV (x
);
568 int yd
= YLOG2DEV (y
);
569 int rd
= XLOG2DEVREL ((long) radius
);
570 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
571 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
576 // If radius is zero use DrawRectangle() instead to avoid
577 // X drawing errors with small radii
580 DrawRectangle( x
, y
, width
, height
);
584 // Draw nothing if transformed w or h is 0
585 if (wd
== 0 || hd
== 0) return;
587 // CMB: adjust size if outline is drawn otherwise the result is
588 // 1 pixel too wide and high
589 if (m_pen
.GetStyle() != wxTRANSPARENT
)
595 // CMB: ensure dd is not larger than rectangle otherwise we
596 // get an hour glass shape
597 if (rw_d
> wd
) rw_d
= wd
;
598 if (rw_d
> hd
) rw_d
= hd
;
601 // For backing pixmap
602 int xd2
= XLOG2DEV_2 (x
);
603 int yd2
= YLOG2DEV_2 (y
);
604 int rd2
= XLOG2DEVREL ((long) radius
);
605 int wd2
= XLOG2DEVREL (width
) ;
606 int hd2
= YLOG2DEVREL (height
) ;
611 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
615 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
617 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
620 // Arcs start from 3 o'clock, positive angles anticlockwise
622 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
623 rw_d
, rh_d
, 90 * 64, 90 * 64);
625 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
626 // rw_d, rh_d, 0, 90 * 64);
627 rw_d
, rh_d
, 0, 91 * 64);
629 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
631 // rw_d, rh_d, 270 * 64, 90 * 64);
632 rw_d
, rh_d
, 269 * 64, 92 * 64);
634 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
635 rw_d
, rh_d
, 180 * 64, 90 * 64);
637 if (m_window
&& m_window
->GetBackingPixmap())
639 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
640 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
641 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
642 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
644 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
645 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
646 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
647 xd2
+ wd2
- rw_d2
, yd2
,
648 // rw_d2, rh_d2, 0, 90 * 64);
649 rw_d2
, rh_d2
, 0, 91 * 64);
650 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
653 // rw_d2, rh_d2, 270 * 64, 90 * 64);
654 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
655 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
656 xd2
, yd2
+ hd2
- rh_d2
,
657 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
661 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
664 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
665 xd
+ wd
- rd
+ 1, yd
);
666 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
667 xd
+ wd
- rd
, yd
+ hd
);
669 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
671 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
672 xd
+ wd
, yd
+ hd
- rd
+ 1);
673 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
674 rw_d
, rh_d
, 90 * 64, 90 * 64);
675 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
676 // rw_d, rh_d, 0, 90 * 64);
677 rw_d
, rh_d
, 0, 91 * 64);
678 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
680 rw_d
, rh_d
, 269 * 64, 92 * 64);
681 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
682 rw_d
, rh_d
, 180 * 64, 90 * 64);
684 if (m_window
&& m_window
->GetBackingPixmap())
686 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
688 xd2
+ wd2
- rd2
+ 1, yd2
);
689 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
690 xd2
+ rd2
, yd2
+ hd2
,
691 xd2
+ wd2
- rd2
, yd2
+ hd2
);
693 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
695 xd2
, yd2
+ hd2
- rd2
);
696 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
697 xd2
+ wd2
, yd2
+ rd2
,
698 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
699 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
701 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
702 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
703 xd2
+ wd2
- rw_d2
, yd2
,
704 // rw_d2, rh_d2, 0, 90 * 64);
705 rw_d2
, rh_d2
, 0, 91 * 64);
706 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
709 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
710 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
711 xd2
, yd2
+ hd2
- rh_d2
,
712 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
715 CalcBoundingBox (x
, y
);
716 CalcBoundingBox (x
+ width
, y
+ height
);
719 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
721 wxCHECK_RET( Ok(), "invalid dc" );
723 // Check for negative width and height
736 static const int angle
= 23040;
742 wd
= XLOG2DEVREL(width
) ;
743 hd
= YLOG2DEVREL(height
) ;
745 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
748 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
749 if (m_window
&& m_window
->GetBackingPixmap())
750 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
751 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
752 XLOG2DEVREL (width
) - WX_GC_CF
,
753 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
756 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
760 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
761 if (m_window
&& m_window
->GetBackingPixmap())
762 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
763 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
764 XLOG2DEVREL (width
) - WX_GC_CF
,
765 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
767 CalcBoundingBox (x
, y
);
768 CalcBoundingBox (x
+ width
, y
+ height
);
772 bool wxWindowDC::CanDrawBitmap() const
774 wxCHECK_MSG( Ok(), false, "invalid dc" );
779 // TODO: use scaled Blit e.g. as per John Price's implementation
780 // in Contrib/Utilities
781 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
782 wxCoord width
, wxCoord height
,
783 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
784 int rop
, bool useMask
,
785 wxCoord xsrcMask
, wxCoord ysrcMask
)
787 wxCHECK_MSG( Ok(), false, "invalid dc" );
789 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
791 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
793 // Be sure that foreground pixels (1) of the Icon will be painted with
794 // foreground colour. [m_textForegroundColour] Background pixels (0)
795 // will be painted with backgound colour (m_textBackgroundColour)
796 // Using ::SetPen is horribly slow, so avoid doing it
797 int oldBackgroundPixel
= -1;
798 int oldForegroundPixel
= -1;
800 if (m_textBackgroundColour
.Ok())
802 oldBackgroundPixel
= m_backgroundPixel
;
803 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
805 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
806 if (m_window
&& m_window
->GetBackingPixmap())
807 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
810 if (m_textForegroundColour
.Ok())
812 oldForegroundPixel
= m_currentColour
.GetPixel();
814 if( m_textForegroundColour
.GetPixel() <= -1 )
815 CalculatePixel( m_textForegroundColour
,
816 m_textForegroundColour
, true);
818 int pixel
= m_textForegroundColour
.GetPixel();
820 SetForegroundPixelWithLogicalFunction(pixel
);
823 // Do bitmap scaling if necessary
825 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
826 Pixmap sourcePixmap
= (Pixmap
) NULL
;
827 double scaleX
, scaleY
;
828 GetUserScale(& scaleX
, & scaleY
);
831 /* TODO: use the mask origin when drawing transparently */
832 if (xsrcMask
== -1 && ysrcMask
== -1)
834 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
837 // Sorry, can't scale masks just yet
838 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
840 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
841 wxBitmap
& bitmap
= memDC
->GetBitmap();
843 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
845 wxImage image
= bitmap
.ConvertToImage();
848 sourcePixmap
= (Pixmap
) bitmap
.GetDrawable();
852 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
853 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
855 image
= image
.Scale(scaledW
, scaledH
);
856 scaledBitmap
= new wxBitmap(image
);
857 sourcePixmap
= (Pixmap
) scaledBitmap
->GetDrawable();
861 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
863 if (m_pixmap
&& sourcePixmap
)
866 int orig
= m_logicalFunction
;
868 SetLogicalFunction (rop
);
870 if (m_display
!= sourceDC
->m_display
)
872 XImage
*cache
= NULL
;
874 if (m_window
&& m_window
->GetBackingPixmap())
875 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
876 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
878 source
->LogicalToDeviceX (xsrc
),
879 source
->LogicalToDeviceY (ysrc
),
880 source
->LogicalToDeviceXRel(width
),
881 source
->LogicalToDeviceYRel(height
),
882 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
885 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
887 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
888 wxBitmap
& sel
= memDC
->GetBitmap();
889 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
891 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
892 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
896 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
897 source
->LogicalToDeviceX (xsrc
),
898 source
->LogicalToDeviceY (ysrc
),
899 source
->LogicalToDeviceXRel(width
),
900 source
->LogicalToDeviceYRel(height
),
901 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
907 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
908 (Region
) m_clipRegion
);
910 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
912 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
916 { //XGCValues values;
917 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
919 if (m_window
&& m_window
->GetBackingPixmap())
921 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
922 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
924 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
925 source
->LogicalToDeviceX (xsrc
),
926 source
->LogicalToDeviceY (ysrc
),
927 source
->LogicalToDeviceXRel(width
),
928 source
->LogicalToDeviceYRel(height
),
929 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
933 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
934 source
->LogicalToDeviceX (xsrc
),
935 source
->LogicalToDeviceY (ysrc
),
936 source
->LogicalToDeviceXRel(width
),
937 source
->LogicalToDeviceYRel(height
),
938 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
941 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
943 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
944 wxBitmap
& sel
= memDC
->GetBitmap();
945 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
947 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
948 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
952 // Check if we're copying from a mono bitmap
953 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
954 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
956 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
957 source
->LogicalToDeviceX (xsrc
),
958 source
->LogicalToDeviceY (ysrc
),
959 source
->LogicalToDeviceXRel(width
),
960 source
->LogicalToDeviceYRel(height
),
961 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
965 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
966 source
->LogicalToDeviceX (xsrc
),
967 source
->LogicalToDeviceY (ysrc
),
968 source
->LogicalToDeviceXRel(width
),
969 source
->LogicalToDeviceYRel(height
),
970 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
976 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
977 (Region
) m_clipRegion
);
979 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
981 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
984 } /* Remote/local (Display*) m_display */
985 CalcBoundingBox (xdest
, ydest
);
986 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
988 SetLogicalFunction(orig
);
992 if (scaledBitmap
) delete scaledBitmap
;
994 if (oldBackgroundPixel
> -1)
996 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
997 if (m_window
&& m_window
->GetBackingPixmap())
998 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1001 if (oldForegroundPixel
> -1)
1003 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1004 if (m_window
&& m_window
->GetBackingPixmap())
1005 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1006 oldForegroundPixel
);
1012 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1014 wxCHECK_RET( Ok(), "invalid dc" );
1016 // Since X draws from the baseline of the text, must add the text height
1020 int slen
= text
.length();
1022 // Set FillStyle, otherwise X will use current stipple!
1023 XGCValues gcV
, gcBackingV
;
1025 XGetGCValues ((Display
*) m_display
, (GC
)m_gc
, GCFillStyle
, &gcV
);
1026 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1027 if (m_window
&& m_window
->GetBackingPixmap())
1029 XGetGCValues ((Display
*) m_display
, (GC
)m_gcBacking
, GCFillStyle
,
1031 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
, FillSolid
);
1035 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1036 text
, &cx
, &cy
, &ascent
, NULL
);
1038 // First draw a rectangle representing the text background, if a text
1039 // background is specified
1040 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1042 wxColour oldPenColour
= m_currentColour
;
1043 m_currentColour
= m_textBackgroundColour
;
1044 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1045 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1046 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1047 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1049 // This separation of the big && test required for gcc2.7/HP UX 9.02
1050 // or pixel value can be corrupted!
1051 sameColour
= (sameColour
&&
1052 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1054 if (!sameColour
|| !GET_OPTIMIZATION
)
1056 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1057 m_currentColour
= m_textBackgroundColour
;
1059 // Set the GC to the required colour
1062 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1063 if (m_window
&& m_window
->GetBackingPixmap())
1064 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1068 m_textBackgroundColour
= oldPenColour
;
1070 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1071 if (m_window
&& m_window
->GetBackingPixmap())
1072 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1073 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1076 // Now set the text foreground and draw the text
1077 if (m_textForegroundColour
.Ok ())
1079 wxColour oldPenColour
= m_currentColour
;
1080 m_currentColour
= m_textForegroundColour
;
1081 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1082 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1083 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1084 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1085 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1087 if (!sameColour
|| !GET_OPTIMIZATION
)
1089 int pixel
= CalculatePixel(m_textForegroundColour
,
1090 m_currentColour
, false);
1092 // Set the GC to the required colour
1095 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1096 if (m_window
&& m_window
->GetBackingPixmap())
1097 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1101 m_textForegroundColour
= oldPenColour
;
1104 // We need to add the ascent, not the whole height, since X draws at the
1105 // point above the descender.
1108 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1109 (XChar2b
*)(char*) (const char*) text
, slen
);
1112 #if wxMOTIF_NEW_FONT_HANDLING
1113 XFontSet fset
= (XFontSet
) m_font
.GetFontSet (m_userScaleY
* m_logicalScaleY
, m_display
);
1114 XmbDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, fset
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1116 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1119 if (m_window
&& m_window
->GetBackingPixmap()) {
1122 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1123 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1124 (XChar2b
*)(char*) (const char*) text
, slen
);
1127 #if wxMOTIF_NEW_FONT_HANDLING
1128 XmbDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), fset
, (GC
) m_gcBacking
,
1129 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1130 wxConstCast(text
.c_str(), char), slen
);
1132 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1133 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1134 wxConstCast(text
.c_str(), char), slen
);
1138 // restore fill style
1139 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, gcV
.fill_style
);
1140 if (m_window
&& m_window
->GetBackingPixmap())
1141 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
,
1142 gcBackingV
.fill_style
);
1145 GetTextExtent (text
, &w
, &h
);
1146 CalcBoundingBox (x
+ w
, y
+ h
);
1147 CalcBoundingBox (x
, y
);
1150 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
,
1155 DrawText(text
, x
, y
);
1159 wxCHECK_RET( Ok(), "invalid dc" );
1161 int oldBackgroundPixel
= -1;
1162 int oldForegroundPixel
= -1;
1163 int foregroundPixel
= -1;
1164 int backgroundPixel
= -1;
1166 if (m_textBackgroundColour
.Ok())
1168 oldBackgroundPixel
= m_backgroundPixel
;
1169 backgroundPixel
= m_textBackgroundColour
.AllocColour(m_display
);
1171 if (m_textForegroundColour
.Ok())
1173 oldForegroundPixel
= m_currentColour
.GetPixel();
1175 if( m_textForegroundColour
.GetPixel() <= -1 )
1176 CalculatePixel( m_textForegroundColour
,
1177 m_textForegroundColour
, true);
1179 foregroundPixel
= m_textForegroundColour
.GetPixel();
1182 // Since X draws from the baseline of the text, must add the text height
1188 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1189 text
, &cx
, &cy
, &ascent
, NULL
);
1191 wxBitmap
src(cx
, cy
);
1193 dc
.SelectObject(src
);
1194 dc
.SetFont(GetFont());
1195 dc
.SetBackground(*wxWHITE_BRUSH
);
1196 dc
.SetBrush(*wxBLACK_BRUSH
);
1198 dc
.DrawText(text
, 0, 0);
1199 dc
.SetFont(wxNullFont
);
1201 // Calculate the size of the rotated bounding box.
1202 double dx
= cos(angle
/ 180.0 * M_PI
);
1203 double dy
= sin(angle
/ 180.0 * M_PI
);
1204 double x4
= cy
* dy
;
1205 double y4
= cy
* dx
;
1206 double x3
= cx
* dx
;
1207 double y3
= -cx
* dy
;
1208 double x2
= x3
+ x4
;
1209 double y2
= y3
+ y4
;
1213 // Create image from the source bitmap after writing the text into it.
1214 wxImage image
= src
.ConvertToImage();
1216 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1217 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1218 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1219 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1221 bool lastFore
= false, lastBack
= false;
1223 // This rotates counterclockwise around the top left corner.
1224 for (int rx
= minx
; rx
< maxx
; rx
++)
1226 for (int ry
= miny
; ry
< maxy
; ry
++)
1228 // transform dest coords to source coords
1229 int sx
= (int) (rx
* dx
- ry
* dy
+ 0.5);
1230 int sy
= - (int) (-ry
* dx
- rx
* dy
+ 0.5);
1231 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1233 bool textPixel
= image
.GetRed(sx
, sy
) == 0;
1235 if (!textPixel
&& m_backgroundMode
!= wxSOLID
)
1238 wxCoord ox
= (wxCoord
) (x1
+ rx
),
1239 oy
= (wxCoord
) (y1
+ ry
);
1240 // draw black pixels, ignore white ones (i.e. transparent b/g)
1241 if (textPixel
&& !lastFore
)
1243 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1248 else if (!textPixel
&& !lastBack
)
1250 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1256 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
,
1257 (GC
) m_gc
, XLOG2DEV (ox
), YLOG2DEV (oy
));
1258 if (m_window
&& m_window
->GetBackingPixmap())
1259 XDrawPoint ((Display
*) m_display
,
1260 (Pixmap
) m_window
->GetBackingPixmap(),
1262 XLOG2DEV_2 (ox
), YLOG2DEV_2 (oy
));
1267 if (oldBackgroundPixel
> -1)
1269 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1270 if (m_window
&& m_window
->GetBackingPixmap())
1271 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1272 oldBackgroundPixel
);
1274 if (oldForegroundPixel
> -1)
1276 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1277 if (m_window
&& m_window
->GetBackingPixmap())
1278 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1279 oldForegroundPixel
);
1282 CalcBoundingBox (minx
, miny
);
1283 CalcBoundingBox (maxx
, maxy
);
1286 bool wxWindowDC::CanGetTextExtent() const
1291 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1292 wxCoord
*descent
, wxCoord
*externalLeading
,
1293 wxFont
*font
) const
1295 wxCHECK_RET( Ok(), "invalid dc" );
1297 const wxFont
* theFont
= font
? font
: &m_font
;
1301 // TODO: this should be an error log function
1302 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1304 if (width
) *width
= -1;
1305 if (height
) *height
= -1;
1309 wxGetTextExtent(m_display
, *theFont
, m_userScaleY
* m_logicalScaleY
,
1310 string
, width
, height
, NULL
, descent
);
1312 if (width
) *width
= XDEV2LOGREL (*width
);
1313 if (height
) *height
= YDEV2LOGREL (*height
);
1314 if (externalLeading
)
1315 *externalLeading
= 0;
1318 wxCoord
wxWindowDC::GetCharWidth() const
1320 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1321 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1325 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1326 "x", &width
, NULL
, NULL
, NULL
);
1328 return XDEV2LOGREL(width
);
1331 wxCoord
wxWindowDC::GetCharHeight() const
1333 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1334 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1338 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1339 "x", NULL
, &height
, NULL
, NULL
);
1341 return XDEV2LOGREL(height
);
1344 void wxWindowDC::DoGetSize( int *width
, int *height
) const
1350 if( m_window
->GetBackingPixmap() )
1352 w
= m_window
->GetPixmapWidth();
1353 h
= m_window
->GetPixmapHeight();
1356 m_window
->GetSize( &w
, &h
);
1359 if( width
) *width
= w
;
1360 if( height
) *height
= h
;
1363 void wxWindowDC::Clear()
1365 wxCHECK_RET( Ok(), "invalid dc" );
1367 wxRect
rect( GetSize() );
1371 void wxWindowDC::Clear(const wxRect
& rect
)
1373 wxCHECK_RET( Ok(), "invalid dc" );
1375 int x
= rect
.x
; int y
= rect
.y
;
1376 int w
= rect
.width
; int h
= rect
.height
;
1378 wxBrush saveBrush
= m_brush
;
1379 SetBrush (m_backgroundBrush
);
1381 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1384 if (m_window
&& m_window
->GetBackingPixmap())
1385 XFillRectangle ((Display
*) m_display
,
1386 (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1389 m_brush
= saveBrush
;
1392 void wxWindowDC::SetFont( const wxFont
&font
)
1394 wxCHECK_RET( Ok(), "invalid dc" );
1403 #if !wxMOTIF_NEW_FONT_HANDLING
1404 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1406 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1407 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1409 if (m_window
&& m_window
->GetBackingPixmap())
1410 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1414 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel
)
1416 if (m_logicalFunction
== wxXOR
)
1419 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1420 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1421 pixel
^ values
.background
);
1422 if (m_window
&& m_window
->GetBackingPixmap())
1423 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1424 pixel
^ values
.background
);
1428 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1429 if (m_window
&& m_window
->GetBackingPixmap())
1430 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1434 int wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1435 bool roundToWhite
) const
1437 const unsigned char wp
= (unsigned char)255;
1440 if(!m_colour
) // Mono display
1442 unsigned char red
= colour
.Red ();
1443 unsigned char blue
= colour
.Blue ();
1444 unsigned char green
= colour
.Green ();
1446 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1447 // not black and roundToWhite was specified
1448 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1451 pixel
= (int)WhitePixel((Display
*) m_display
,
1452 DefaultScreen((Display
*) m_display
));
1453 curCol
.SetPixel(pixel
);
1454 colour
.SetPixel(pixel
);
1459 pixel
= (int)BlackPixel((Display
*) m_display
,
1460 DefaultScreen((Display
*) m_display
));
1461 curCol
.SetPixel(pixel
);
1462 colour
.SetPixel(pixel
);
1468 pixel
= colour
.AllocColour((Display
*) m_display
);
1469 curCol
.SetPixel(pixel
);
1475 void wxWindowDC::SetPen( const wxPen
&pen
)
1477 wxCHECK_RET( Ok(), "invalid dc" );
1483 wxBitmap oldStipple
= m_currentStipple
;
1484 int oldStyle
= m_currentStyle
;
1485 int oldFill
= m_currentFill
;
1486 int old_pen_width
= m_currentPenWidth
;
1487 int old_pen_join
= m_currentPenJoin
;
1488 int old_pen_cap
= m_currentPenCap
;
1489 int old_pen_nb_dash
= m_currentPenDashCount
;
1490 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1492 wxColour oldPenColour
= m_currentColour
;
1493 m_currentColour
= m_pen
.GetColour ();
1494 m_currentStyle
= m_pen
.GetStyle ();
1495 m_currentFill
= m_pen
.GetStyle (); // TODO?
1496 m_currentPenWidth
= m_pen
.GetWidth ();
1497 m_currentPenJoin
= m_pen
.GetJoin ();
1498 m_currentPenCap
= m_pen
.GetCap ();
1499 m_currentPenDashCount
= m_pen
.GetDashCount();
1500 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1502 if (m_currentStyle
== wxSTIPPLE
)
1503 m_currentStipple
= * m_pen
.GetStipple ();
1505 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1506 oldFill
== m_currentFill
&&
1507 old_pen_join
== m_currentPenJoin
&&
1508 old_pen_cap
== m_currentPenCap
&&
1509 old_pen_nb_dash
== m_currentPenDashCount
&&
1510 old_pen_dash
== m_currentPenDash
&&
1511 old_pen_width
== m_currentPenWidth
);
1513 bool sameColour
= (oldPenColour
.Ok () &&
1514 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1515 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1516 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1517 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1519 if (!sameStyle
|| !GET_OPTIMIZATION
)
1521 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1522 if (scaled_width
< 0)
1528 static const wxX11Dash dotted
[] = {2, 5};
1529 static const wxX11Dash short_dashed
[] = {4, 4};
1530 static const wxX11Dash long_dashed
[] = {4, 8};
1531 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1533 // We express dash pattern in pen width unit, so we are
1534 // independent of zoom factor and so on...
1536 const wxX11Dash
*req_dash
;
1538 switch (m_pen
.GetStyle ())
1541 req_nb_dash
= m_currentPenDashCount
;
1542 req_dash
= m_currentPenDash
;
1543 style
= LineOnOffDash
;
1548 style
= LineOnOffDash
;
1552 req_dash
= short_dashed
;
1553 style
= LineOnOffDash
;
1557 req_dash
= long_dashed
;
1558 style
= LineOnOffDash
;
1562 req_dash
= dotted_dashed
;
1563 style
= LineOnOffDash
;
1570 req_dash
= (wxX11Dash
*)NULL
;
1574 if (req_dash
&& req_nb_dash
)
1576 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1579 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1580 for (int i
= 0; i
< req_nb_dash
; i
++)
1581 real_req_dash
[i
] = req_dash
[i
] * factor
;
1582 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1584 if (m_window
&& m_window
->GetBackingPixmap())
1585 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1586 delete[]real_req_dash
;
1590 // No Memory. We use non-scaled dash pattern...
1591 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1593 if (m_window
&& m_window
->GetBackingPixmap())
1594 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1598 switch (m_pen
.GetCap ())
1600 case wxCAP_PROJECTING
:
1601 cap
= CapProjecting
;
1608 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1612 switch (m_pen
.GetJoin ())
1626 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1628 if (m_window
&& m_window
->GetBackingPixmap())
1629 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1632 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1636 oldStipple
= wxNullBitmap
; // For later reset!!
1638 switch (m_currentFill
)
1640 case wxBDIAGONAL_HATCH
:
1641 if (bdiag
== (Pixmap
) 0)
1642 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1643 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1644 bdiag_bits
, bdiag_width
, bdiag_height
);
1647 case wxFDIAGONAL_HATCH
:
1648 if (fdiag
== (Pixmap
) 0)
1649 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1650 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1651 fdiag_bits
, fdiag_width
, fdiag_height
);
1655 if (cross
== (Pixmap
) 0)
1656 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1657 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1658 cross_bits
, cross_width
, cross_height
);
1661 case wxHORIZONTAL_HATCH
:
1662 if (horiz
== (Pixmap
) 0)
1663 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1664 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1665 horiz_bits
, horiz_width
, horiz_height
);
1668 case wxVERTICAL_HATCH
:
1669 if (verti
== (Pixmap
) 0)
1670 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1671 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1672 verti_bits
, verti_width
, verti_height
);
1675 case wxCROSSDIAG_HATCH
:
1677 if (cdiag
== (Pixmap
) 0)
1678 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1679 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1680 cdiag_bits
, cdiag_width
, cdiag_height
);
1684 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1686 if (m_window
&& m_window
->GetBackingPixmap())
1687 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1689 else if (m_currentStipple
.Ok()
1690 && ((m_currentStipple
!= oldStipple
) || !GET_OPTIMIZATION
))
1692 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetDrawable());
1694 if (m_window
&& m_window
->GetBackingPixmap())
1695 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetDrawable());
1698 if ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
)
1702 if (m_currentFill
== wxSTIPPLE
)
1703 fill_style
= FillStippled
;
1704 else if (IS_HATCH (m_currentFill
))
1705 fill_style
= FillStippled
;
1707 fill_style
= FillSolid
;
1708 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1709 if (m_window
&& m_window
->GetBackingPixmap())
1710 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1713 // must test m_logicalFunction, because it involves background!
1714 if (!sameColour
|| !GET_OPTIMIZATION
1715 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1718 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1719 pixel
= m_backgroundPixel
;
1722 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, false);
1725 // Finally, set the GC to the required colour
1727 SetForegroundPixelWithLogicalFunction(pixel
);
1730 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1735 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1737 wxCHECK_RET( Ok(), "invalid dc" );
1741 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1744 int oldFill
= m_currentFill
;
1745 wxBitmap oldStipple
= m_currentStipple
;
1747 m_autoSetting
|= 0x1;
1749 m_currentFill
= m_brush
.GetStyle ();
1750 if (m_currentFill
== wxSTIPPLE
)
1751 m_currentStipple
= * m_brush
.GetStipple ();
1753 wxColour
oldBrushColour(m_currentColour
);
1754 m_currentColour
= m_brush
.GetColour ();
1756 bool sameColour
= (oldBrushColour
.Ok () &&
1757 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1758 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1759 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1760 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1762 int stippleDepth
= -1;
1764 if ((oldFill
!= m_brush
.GetStyle ()) || !GET_OPTIMIZATION
)
1766 switch (brush
.GetStyle ())
1771 stippleDepth
= m_currentStipple
.GetDepth();
1773 case wxBDIAGONAL_HATCH
:
1774 case wxCROSSDIAG_HATCH
:
1775 case wxFDIAGONAL_HATCH
:
1777 case wxHORIZONTAL_HATCH
:
1778 case wxVERTICAL_HATCH
:
1780 if (stippleDepth
== -1) stippleDepth
= 1;
1782 // Chris Breeze 23/07/97: use background mode to
1783 // determine whether fill style should be solid or
1785 int style
= stippleDepth
== 1 ?
1786 (m_backgroundMode
== wxSOLID
?
1787 FillOpaqueStippled
: FillStippled
) :
1789 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1790 if (m_window
&& m_window
->GetBackingPixmap())
1791 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1796 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1797 if (m_window
&& m_window
->GetBackingPixmap())
1798 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
,
1803 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1807 switch (m_currentFill
)
1809 case wxBDIAGONAL_HATCH
:
1810 if (bdiag
== (Pixmap
) 0)
1811 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1812 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1813 bdiag_bits
, bdiag_width
, bdiag_height
);
1816 case wxFDIAGONAL_HATCH
:
1817 if (fdiag
== (Pixmap
) 0)
1818 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1819 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1820 fdiag_bits
, fdiag_width
, fdiag_height
);
1824 if (cross
== (Pixmap
) 0)
1825 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1826 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1827 cross_bits
, cross_width
, cross_height
);
1830 case wxHORIZONTAL_HATCH
:
1831 if (horiz
== (Pixmap
) 0)
1832 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1833 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1834 horiz_bits
, horiz_width
, horiz_height
);
1837 case wxVERTICAL_HATCH
:
1838 if (verti
== (Pixmap
) 0)
1839 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1840 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1841 verti_bits
, verti_width
, verti_height
);
1844 case wxCROSSDIAG_HATCH
:
1846 if (cdiag
== (Pixmap
) 0)
1847 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1848 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1849 cdiag_bits
, cdiag_width
, cdiag_height
);
1853 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1855 if (m_window
&& m_window
->GetBackingPixmap())
1856 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1858 // X can forget the stipple value when resizing a window (apparently)
1859 // so always set the stipple.
1860 else if (m_currentFill
!= wxSOLID
&& m_currentFill
!= wxTRANSPARENT
&&
1861 m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1863 if (m_currentStipple
.GetDepth() == 1)
1865 XSetStipple ((Display
*) m_display
, (GC
) m_gc
,
1866 (Pixmap
) m_currentStipple
.GetDrawable());
1867 if (m_window
&& m_window
->GetBackingPixmap())
1868 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
,
1869 (Pixmap
) m_currentStipple
.GetDrawable());
1873 XSetTile ((Display
*) m_display
, (GC
) m_gc
,
1874 (Pixmap
) m_currentStipple
.GetDrawable());
1875 if (m_window
&& m_window
->GetBackingPixmap())
1876 XSetTile ((Display
*) m_display
,(GC
) m_gcBacking
,
1877 (Pixmap
) m_currentStipple
.GetDrawable());
1881 // must test m_logicalFunction, because it involves background!
1882 if (!sameColour
|| !GET_OPTIMIZATION
|| m_logicalFunction
== wxXOR
)
1884 int pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, true);
1887 SetForegroundPixelWithLogicalFunction(pixel
);
1890 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1893 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1895 wxCHECK_RET( Ok(), "invalid dc" );
1897 m_backgroundBrush
= brush
;
1899 if (!m_backgroundBrush
.Ok())
1902 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1904 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1905 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1906 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
1907 if (m_window
&& m_window
->GetBackingPixmap())
1908 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1912 void wxWindowDC::SetLogicalFunction( int function
)
1914 wxCHECK_RET( Ok(), "invalid dc" );
1919 if (m_logicalFunction
== function
)
1925 x_function
= GXclear
;
1931 x_function
= GXinvert
;
1934 x_function
= GXorReverse
;
1937 x_function
= GXandReverse
;
1946 x_function
= GXandInverted
;
1949 x_function
= GXnoop
;
1955 x_function
= GXequiv
;
1958 x_function
= GXcopyInverted
;
1961 x_function
= GXorInverted
;
1964 x_function
= GXnand
;
1971 x_function
= GXcopy
;
1975 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1976 if (m_window
&& m_window
->GetBackingPixmap())
1977 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1979 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1980 /* MATTHEW: [9] Need to redo pen simply */
1981 m_autoSetting
|= 0x2;
1983 m_logicalFunction
= function
;
1987 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1989 wxCHECK_RET( Ok(), "invalid dc" );
1991 m_textForegroundColour
= col
;
1994 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1996 wxCHECK_RET( Ok(), "invalid dc" );
1998 m_textBackgroundColour
= col
;
2001 void wxWindowDC::SetBackgroundMode( int mode
)
2003 m_backgroundMode
= mode
;
2006 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2011 /* Use GetXColormap */
2012 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2013 (Colormap
) palette
.GetXColormap());
2015 /* Use wxGetMainColormap */
2016 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2017 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2021 static void wxCopyRegion( WXRegion src
, WXRegion
& dst
)
2024 dst
= XCreateRegion();
2025 XUnionRegion( (Region
)src
, (Region
)src
, (Region
)dst
);
2028 // Helper function; userRegion is the region set by calling SetClippingRegion
2029 void wxWindowDC::SetDCClipping( WXRegion userRegion
)
2031 bool hasUpdateRegion
= m_window
&& m_window
->GetUpdateRegion().Ok();
2032 // this means that we should start the clip region from scratch,
2033 // or from the update region, if any
2037 XDestroyRegion( (Region
)m_clipRegion
);
2038 m_clipRegion
= (WXRegion
)NULL
;
2040 if( hasUpdateRegion
)
2041 wxCopyRegion( m_window
->GetUpdateRegion().GetX11Region(),
2044 // intersect the user region, if any, with the
2045 // exisiting clip region
2046 else // if( userRegion )
2049 wxCopyRegion( userRegion
, m_clipRegion
);
2051 XIntersectRegion( (Region
)m_clipRegion
,
2052 (Region
)userRegion
, (Region
)m_clipRegion
);
2056 XSetRegion( (Display
*)m_display
, (GC
)m_gc
, (Region
)m_clipRegion
);
2058 XSetClipMask( (Display
*)m_display
, (GC
)m_gc
, None
);
2061 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
,
2062 wxCoord width
, wxCoord height
)
2064 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2066 wxRegion
temp(x
, y
, width
, height
);
2068 SetDCClipping(temp
.GetX11Region());
2070 // Needs to work differently for Pixmap: without this,
2071 // there's a nasty (Display*) m_display bug. 8/12/94
2072 if (m_window
&& m_window
->GetBackingPixmap())
2074 XRectangle rects
[1];
2075 rects
[0].x
= XLOG2DEV_2(x
);
2076 rects
[0].y
= YLOG2DEV_2(y
);
2077 rects
[0].width
= XLOG2DEVREL(width
);
2078 rects
[0].height
= YLOG2DEVREL(height
);
2079 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2080 0, 0, rects
, 1, Unsorted
);
2084 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2086 wxRect box
= region
.GetBox();
2088 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2090 SetDCClipping(region
.GetX11Region());
2092 // Needs to work differently for Pixmap: without this,
2093 // there's a nasty (Display*) m_display bug. 8/12/94
2094 if (m_window
&& m_window
->GetBackingPixmap())
2096 XRectangle rects
[1];
2097 rects
[0].x
= XLOG2DEV_2(box
.x
);
2098 rects
[0].y
= YLOG2DEV_2(box
.y
);
2099 rects
[0].width
= XLOG2DEVREL(box
.width
);
2100 rects
[0].height
= YLOG2DEVREL(box
.height
);
2101 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2102 0, 0, rects
, 1, Unsorted
);
2107 void wxWindowDC::DestroyClippingRegion()
2109 wxDC::DestroyClippingRegion();
2111 SetDCClipping(NULL
);
2113 if (m_window
&& m_window
->GetBackingPixmap())
2114 XSetClipMask ((Display
*) m_display
, (GC
) m_gcBacking
, None
);
2117 // Resolution in pixels per logical inch
2118 wxSize
wxWindowDC::GetPPI() const
2121 return wxSize(100, 100);
2124 int wxWindowDC::GetDepth() const
2133 // ----------------------------------------------------------------------------
2135 // ----------------------------------------------------------------------------
2137 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2139 // Set the clipping region.to the update region
2140 SetDCClipping((WXRegion
)NULL
);
2143 wxPaintDC::~wxPaintDC()
2146 m_window
->ClearUpdateRegion();
2147 SetDCClipping((WXRegion
)NULL
);
2150 // ----------------------------------------------------------------------------
2151 // private functions
2152 // ----------------------------------------------------------------------------
2155 Used when copying between drawables on different (Display*) m_displays. Not
2156 very fast, but better than giving up.
2159 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2160 Drawable src
, Drawable dest
,
2163 unsigned int w
, unsigned int h
,
2164 int destx
, int desty
,
2165 bool more
, XImage
**cache
)
2167 XImage
*image
, *destimage
;
2168 Colormap destcm
, srccm
;
2169 static const int CACHE_SIZE
= 256;
2172 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2173 int k
, cache_pos
, all_cache
;
2175 if (!cache
|| !*cache
)
2176 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2180 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2182 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2183 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2188 for (i
= 0; i
< w
; i
++)
2189 for (j
= 0; j
< h
; j
++) {
2190 unsigned long pixel
;
2193 pixel
= XGetPixel(image
, i
, j
);
2194 for (k
= cache_pos
; k
--; )
2195 if (cachesrc
[k
] == pixel
) {
2196 pixel
= cachedest
[k
];
2200 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2201 if (cachesrc
[k
] == pixel
) {
2202 pixel
= cachedest
[k
];
2206 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2207 XQueryColor(src_display
, srccm
, &xcol
);
2208 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2210 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2212 if (++cache_pos
>= CACHE_SIZE
) {
2218 XPutPixel(destimage
, i
, j
, pixel
);
2221 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2222 XDestroyImage(destimage
);
2227 XDestroyImage(image
);
2232 /* Helper function for 16-bit fonts */
2233 static int str16len(const char *s
)
2237 while (s
[0] && s
[1]) {