1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 About pens, brushes, and the m_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 m_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 m_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"
47 #include "wx/window.h"
50 #include "wx/dcmemory.h"
55 #pragma message disable nosimpint
59 #pragma message enable nosimpint
62 #include "wx/motif/private.h"
65 #include <float.h> // for M_PI
75 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 // Fudge factor (VZ: what??)
84 // ----------------------------------------------------------------------------
86 // ----------------------------------------------------------------------------
88 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
89 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
90 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
93 // IS_HATCH exists for WXWIN_COMPATIBILITY_2_4 only
94 // but wxMotif needs it for its internals here
95 #define IS_HATCH(s) ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH)
98 // FIXME: left over after removal of wxDC::GetOptimization()
99 #define GET_OPTIMIZATION false
101 // ----------------------------------------------------------------------------
103 // ----------------------------------------------------------------------------
105 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
106 Drawable src
, Drawable dest
,
109 unsigned int w
, unsigned int h
,
110 int destx
, int desty
,
111 bool more
, XImage
**cache
);
113 // ============================================================================
115 // ============================================================================
118 * compare two doubles and return the larger rounded
121 static int roundmax(double a
, double b
)
123 return (int)((a
> b
? a
: b
) + 0.5);
127 * compare two doubles and return the smaller rounded
130 static int roundmin(double a
, double b
)
132 return (int)((a
< b
? a
: b
) - 0.5);
136 // ----------------------------------------------------------------------------
138 // ----------------------------------------------------------------------------
140 void wxWindowDC::Init()
143 m_gcBacking
= (WXGC
) 0;
145 m_backgroundPixel
= -1;
146 m_currentPenWidth
= 1;
147 m_currentPenJoin
= -1;
148 m_currentPenDashCount
= -1;
149 m_currentPenDash
= (wxX11Dash
*) NULL
;
152 m_colour
= wxColourDisplay();
153 m_display
= (WXDisplay
*) NULL
;
154 m_pixmap
= (WXPixmap
) 0;
157 m_clipRegion
= (WXRegion
) 0;
160 wxWindowDC::wxWindowDC()
165 wxWindowDC::wxWindowDC( wxWindow
*window
)
167 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
172 m_font
= window
->GetFont();
175 m_display
= window
->GetXDisplay();
176 m_pixmap
= window
->GetXWindow();
177 Display
* display
= (Display
*) m_display
;
179 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
182 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
183 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
184 gcvalues
.graphics_exposures
= False
;
185 gcvalues
.subwindow_mode
= IncludeInferiors
;
186 gcvalues
.line_width
= 1;
187 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
188 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
191 if (m_window
->GetBackingPixmap())
193 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
194 DefaultScreen (display
)),
195 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
199 m_backgroundPixel
= (int) gcvalues
.background
;
201 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
204 wxWindowDC::~wxWindowDC()
207 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
211 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
212 m_gcBacking
= (WXGC
) 0;
215 XDestroyRegion ((Region
) m_clipRegion
);
216 m_clipRegion
= (WXRegion
) 0;
219 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
220 const wxColour
& col
, int style
);
222 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
223 const wxColour
& col
, int style
)
225 return wxDoFloodFill(this, x
, y
, col
, style
);
228 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
230 // Generic (and therefore rather inefficient) method.
231 // Could be improved.
233 wxBitmap
bitmap(1, 1);
234 memdc
.SelectObject(bitmap
);
235 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
236 memdc
.SelectObject(wxNullBitmap
);
237 wxImage image
= bitmap
.ConvertToImage();
238 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
242 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
244 wxCHECK_RET( Ok(), "invalid dc" );
246 int x1d
, y1d
, x2d
, y2d
;
256 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
258 if (m_window
&& m_window
->GetBackingPixmap())
259 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
260 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
261 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
263 CalcBoundingBox(x1
, y1
);
264 CalcBoundingBox(x2
, y2
);
267 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
269 wxCHECK_RET( Ok(), "invalid dc" );
274 int xx
= XLOG2DEV (x
);
275 int yy
= YLOG2DEV (y
);
277 wxDisplaySize (&ww
, &hh
);
278 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
280 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
283 if (m_window
&& m_window
->GetBackingPixmap())
287 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
290 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
296 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
298 wxCHECK_RET( Ok(), "invalid dc" );
300 int xx1
= XLOG2DEV (x1
);
301 int yy1
= YLOG2DEV (y1
);
302 int xx2
= XLOG2DEV (x2
);
303 int yy2
= YLOG2DEV (y2
);
304 int xxc
= XLOG2DEV (xc
);
305 int yyc
= YLOG2DEV (yc
);
306 int xxc_2
= XLOG2DEV_2 (xc
);
307 int yyc_2
= YLOG2DEV_2 (yc
);
309 wxCoord dx
= xx1
- xxc
;
310 wxCoord dy
= yy1
- yyc
;
311 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
312 wxCoord r
= (wxCoord
) radius
;
314 double radius1
, radius2
;
316 if (xx1
== xx2
&& yy1
== yy2
)
321 else if (radius
== 0.0)
322 radius1
= radius2
= 0.0;
331 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
339 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
343 int alpha1
= (int) radius1
;
344 int alpha2
= (int) (radius2
- radius1
);
347 while (alpha2
> 360 * 64)
350 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
353 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
354 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
356 if (m_window
&& m_window
->GetBackingPixmap())
357 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
358 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
362 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
366 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
367 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
369 if (m_window
&& m_window
->GetBackingPixmap())
370 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
371 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
373 CalcBoundingBox (x1
, y1
);
374 CalcBoundingBox (x2
, y2
);
377 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
379 wxCHECK_RET( Ok(), "invalid dc" );
385 wd
= XLOG2DEVREL(width
);
386 hd
= YLOG2DEVREL(height
);
388 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
389 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
390 int start
= int(sa
*64);
391 int end
= int(ea
*64);
392 if (start
<0) start
+=360*64;
393 if (end
<0) end
+=360*64;
394 if (end
>start
) end
-=start
;
395 else end
+=360*64-start
;
397 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
399 m_autoSetting
= true; // must be reset
402 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
404 if (m_window
&& m_window
->GetBackingPixmap())
405 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
406 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
409 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
413 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
414 if (m_window
&& m_window
->GetBackingPixmap())
415 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
416 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
418 CalcBoundingBox (x
, y
);
419 CalcBoundingBox (x
+ width
, y
+ height
);
422 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
424 wxCHECK_RET( Ok(), "invalid dc" );
426 if (m_pen
.Ok() && m_autoSetting
)
429 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
430 if (m_window
&& m_window
->GetBackingPixmap())
431 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
433 CalcBoundingBox (x
, y
);
436 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
438 wxCHECK_RET( Ok(), "invalid dc" );
440 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
445 XPoint
*xpoints
= new XPoint
[n
];
448 for (i
= 0; i
< n
; i
++)
450 xpoints
[i
].x
= (short)XLOG2DEV (points
[i
].x
+ xoffset
);
451 xpoints
[i
].y
= (short)YLOG2DEV (points
[i
].y
+ yoffset
);
453 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
455 if (m_window
&& m_window
->GetBackingPixmap())
457 for (i
= 0; i
< n
; i
++)
459 xpoints
[i
].x
= (short)XLOG2DEV_2 (points
[i
].x
+ xoffset
);
460 xpoints
[i
].y
= (short)YLOG2DEV_2 (points
[i
].y
+ yoffset
);
462 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
468 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
469 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
471 wxCHECK_RET( Ok(), "invalid dc" );
473 XPoint
*xpoints1
= new XPoint
[n
+ 1];
474 XPoint
*xpoints2
= new XPoint
[n
+ 1];
476 for (i
= 0; i
< n
; i
++)
478 xpoints1
[i
].x
= (short)XLOG2DEV (points
[i
].x
+ xoffset
);
479 xpoints1
[i
].y
= (short)YLOG2DEV (points
[i
].y
+ yoffset
);
480 xpoints2
[i
].x
= (short)XLOG2DEV_2 (points
[i
].x
+ xoffset
);
481 xpoints2
[i
].y
= (short)YLOG2DEV_2 (points
[i
].y
+ yoffset
);
482 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
485 // Close figure for XDrawLines (not needed for XFillPolygon)
486 xpoints1
[i
].x
= xpoints1
[0].x
;
487 xpoints1
[i
].y
= xpoints1
[0].y
;
488 xpoints2
[i
].x
= xpoints2
[0].x
;
489 xpoints2
[i
].y
= xpoints2
[0].y
;
491 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
494 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
495 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
496 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
497 if (m_window
&& m_window
->GetBackingPixmap())
499 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
500 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
501 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
502 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
506 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
510 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
512 if (m_window
&& m_window
->GetBackingPixmap())
513 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
520 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
522 wxCHECK_RET( Ok(), "invalid dc" );
524 int xd
, yd
, wfd
, hfd
, wd
, hd
;
528 wfd
= XLOG2DEVREL(width
);
530 hfd
= YLOG2DEVREL(height
);
533 if (wfd
== 0 || hfd
== 0) return;
534 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
535 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
537 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
540 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
542 if (m_window
&& m_window
->GetBackingPixmap())
543 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
544 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
548 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
552 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
554 if (m_window
&& m_window
->GetBackingPixmap())
555 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
556 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
559 CalcBoundingBox (x
, y
);
560 CalcBoundingBox (x
+ width
, y
+ height
);
563 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
565 wxCHECK_RET( Ok(), "invalid dc" );
567 // If radius is negative, it's a proportion of the smaller dimension.
569 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
571 int xd
= XLOG2DEV (x
);
572 int yd
= YLOG2DEV (y
);
573 int rd
= XLOG2DEVREL ((long) radius
);
574 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
575 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
580 // If radius is zero use DrawRectangle() instead to avoid
581 // X drawing errors with small radii
584 DrawRectangle( x
, y
, width
, height
);
588 // Draw nothing if transformed w or h is 0
589 if (wd
== 0 || hd
== 0) return;
591 // CMB: adjust size if outline is drawn otherwise the result is
592 // 1 pixel too wide and high
593 if (m_pen
.GetStyle() != wxTRANSPARENT
)
599 // CMB: ensure dd is not larger than rectangle otherwise we
600 // get an hour glass shape
601 if (rw_d
> wd
) rw_d
= wd
;
602 if (rw_d
> hd
) rw_d
= hd
;
605 // For backing pixmap
606 int xd2
= XLOG2DEV_2 (x
);
607 int yd2
= YLOG2DEV_2 (y
);
608 int rd2
= XLOG2DEVREL ((long) radius
);
609 int wd2
= XLOG2DEVREL (width
) ;
610 int hd2
= YLOG2DEVREL (height
) ;
615 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
619 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
621 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
624 // Arcs start from 3 o'clock, positive angles anticlockwise
626 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
627 rw_d
, rh_d
, 90 * 64, 90 * 64);
629 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
630 // rw_d, rh_d, 0, 90 * 64);
631 rw_d
, rh_d
, 0, 91 * 64);
633 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
635 // rw_d, rh_d, 270 * 64, 90 * 64);
636 rw_d
, rh_d
, 269 * 64, 92 * 64);
638 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
639 rw_d
, rh_d
, 180 * 64, 90 * 64);
641 if (m_window
&& m_window
->GetBackingPixmap())
643 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
644 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
645 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
646 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
648 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
649 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
650 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
651 xd2
+ wd2
- rw_d2
, yd2
,
652 // rw_d2, rh_d2, 0, 90 * 64);
653 rw_d2
, rh_d2
, 0, 91 * 64);
654 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
657 // rw_d2, rh_d2, 270 * 64, 90 * 64);
658 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
659 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
660 xd2
, yd2
+ hd2
- rh_d2
,
661 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
665 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
668 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
669 xd
+ wd
- rd
+ 1, yd
);
670 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
671 xd
+ wd
- rd
, yd
+ hd
);
673 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
675 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
676 xd
+ wd
, yd
+ hd
- rd
+ 1);
677 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
678 rw_d
, rh_d
, 90 * 64, 90 * 64);
679 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
680 // rw_d, rh_d, 0, 90 * 64);
681 rw_d
, rh_d
, 0, 91 * 64);
682 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
684 rw_d
, rh_d
, 269 * 64, 92 * 64);
685 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
686 rw_d
, rh_d
, 180 * 64, 90 * 64);
688 if (m_window
&& m_window
->GetBackingPixmap())
690 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
692 xd2
+ wd2
- rd2
+ 1, yd2
);
693 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
694 xd2
+ rd2
, yd2
+ hd2
,
695 xd2
+ wd2
- rd2
, yd2
+ hd2
);
697 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
699 xd2
, yd2
+ hd2
- rd2
);
700 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
701 xd2
+ wd2
, yd2
+ rd2
,
702 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
703 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
705 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
706 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
707 xd2
+ wd2
- rw_d2
, yd2
,
708 // rw_d2, rh_d2, 0, 90 * 64);
709 rw_d2
, rh_d2
, 0, 91 * 64);
710 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
713 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
714 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
715 xd2
, yd2
+ hd2
- rh_d2
,
716 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
719 CalcBoundingBox (x
, y
);
720 CalcBoundingBox (x
+ width
, y
+ height
);
723 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
725 wxCHECK_RET( Ok(), "invalid dc" );
727 // Check for negative width and height
740 static const int angle
= 23040;
746 wd
= XLOG2DEVREL(width
) ;
747 hd
= YLOG2DEVREL(height
) ;
749 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
752 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
753 if (m_window
&& m_window
->GetBackingPixmap())
754 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
755 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
756 XLOG2DEVREL (width
) - WX_GC_CF
,
757 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
760 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
764 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
765 if (m_window
&& m_window
->GetBackingPixmap())
766 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
767 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
768 XLOG2DEVREL (width
) - WX_GC_CF
,
769 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
771 CalcBoundingBox (x
, y
);
772 CalcBoundingBox (x
+ width
, y
+ height
);
776 bool wxWindowDC::CanDrawBitmap() const
778 wxCHECK_MSG( Ok(), false, "invalid dc" );
783 // TODO: use scaled Blit e.g. as per John Price's implementation
784 // in Contrib/Utilities
785 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
786 wxCoord width
, wxCoord height
,
787 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
788 int rop
, bool useMask
,
789 wxCoord xsrcMask
, wxCoord ysrcMask
)
791 wxCHECK_MSG( Ok(), false, "invalid dc" );
793 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
795 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
797 // Be sure that foreground pixels (1) of the Icon will be painted with
798 // foreground colour. [m_textForegroundColour] Background pixels (0)
799 // will be painted with backgound colour (m_textBackgroundColour)
800 // Using ::SetPen is horribly slow, so avoid doing it
801 int oldBackgroundPixel
= -1;
802 int oldForegroundPixel
= -1;
804 if (m_textBackgroundColour
.Ok())
806 oldBackgroundPixel
= m_backgroundPixel
;
807 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
809 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
810 if (m_window
&& m_window
->GetBackingPixmap())
811 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
814 if (m_textForegroundColour
.Ok())
816 oldForegroundPixel
= m_currentColour
.GetPixel();
818 if( m_textForegroundColour
.GetPixel() <= -1 )
819 CalculatePixel( m_textForegroundColour
,
820 m_textForegroundColour
, true);
822 int pixel
= m_textForegroundColour
.GetPixel();
824 SetForegroundPixelWithLogicalFunction(pixel
);
827 // Do bitmap scaling if necessary
829 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
830 Pixmap sourcePixmap
= (Pixmap
) NULL
;
831 double scaleX
, scaleY
;
832 GetUserScale(& scaleX
, & scaleY
);
835 /* TODO: use the mask origin when drawing transparently */
836 if (xsrcMask
== -1 && ysrcMask
== -1)
838 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
841 // Sorry, can't scale masks just yet
842 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
844 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
845 wxBitmap
& bitmap
= memDC
->GetBitmap();
847 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
849 wxImage image
= bitmap
.ConvertToImage();
852 sourcePixmap
= (Pixmap
) bitmap
.GetDrawable();
856 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
857 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
859 image
= image
.Scale(scaledW
, scaledH
);
860 scaledBitmap
= new wxBitmap(image
);
861 sourcePixmap
= (Pixmap
) scaledBitmap
->GetDrawable();
865 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
867 if (m_pixmap
&& sourcePixmap
)
870 int orig
= m_logicalFunction
;
872 SetLogicalFunction (rop
);
874 if (m_display
!= sourceDC
->m_display
)
876 XImage
*cache
= NULL
;
878 if (m_window
&& m_window
->GetBackingPixmap())
879 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
880 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
882 source
->LogicalToDeviceX (xsrc
),
883 source
->LogicalToDeviceY (ysrc
),
884 source
->LogicalToDeviceXRel(width
),
885 source
->LogicalToDeviceYRel(height
),
886 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
889 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
891 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
892 wxBitmap
& sel
= memDC
->GetBitmap();
893 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
895 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
896 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
900 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
901 source
->LogicalToDeviceX (xsrc
),
902 source
->LogicalToDeviceY (ysrc
),
903 source
->LogicalToDeviceXRel(width
),
904 source
->LogicalToDeviceYRel(height
),
905 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
911 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
912 (Region
) m_clipRegion
);
914 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
));
980 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
981 (Region
) m_clipRegion
);
983 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
985 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
988 } /* Remote/local (Display*) m_display */
989 CalcBoundingBox (xdest
, ydest
);
990 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
992 SetLogicalFunction(orig
);
996 if (scaledBitmap
) delete scaledBitmap
;
998 if (oldBackgroundPixel
> -1)
1000 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1001 if (m_window
&& m_window
->GetBackingPixmap())
1002 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1003 oldBackgroundPixel
);
1005 if (oldForegroundPixel
> -1)
1007 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1008 if (m_window
&& m_window
->GetBackingPixmap())
1009 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1010 oldForegroundPixel
);
1016 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1018 wxCHECK_RET( Ok(), "invalid dc" );
1020 // Since X draws from the baseline of the text, must add the text height
1024 int slen
= text
.length();
1026 // Set FillStyle, otherwise X will use current stipple!
1027 XGCValues gcV
, gcBackingV
;
1029 XGetGCValues ((Display
*) m_display
, (GC
)m_gc
, GCFillStyle
, &gcV
);
1030 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1031 if (m_window
&& m_window
->GetBackingPixmap())
1033 XGetGCValues ((Display
*) m_display
, (GC
)m_gcBacking
, GCFillStyle
,
1035 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
, FillSolid
);
1039 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1040 text
, &cx
, &cy
, &ascent
, NULL
);
1042 // First draw a rectangle representing the text background, if a text
1043 // background is specified
1044 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1046 wxColour oldPenColour
= m_currentColour
;
1047 m_currentColour
= m_textBackgroundColour
;
1048 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1049 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1050 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1051 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1053 // This separation of the big && test required for gcc2.7/HP UX 9.02
1054 // or pixel value can be corrupted!
1055 sameColour
= (sameColour
&&
1056 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1058 if (!sameColour
|| !GET_OPTIMIZATION
)
1060 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1061 m_currentColour
= m_textBackgroundColour
;
1063 // Set the GC to the required colour
1066 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1067 if (m_window
&& m_window
->GetBackingPixmap())
1068 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1072 m_textBackgroundColour
= oldPenColour
;
1074 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1075 if (m_window
&& m_window
->GetBackingPixmap())
1076 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1077 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1080 // Now set the text foreground and draw the text
1081 if (m_textForegroundColour
.Ok ())
1083 wxColour oldPenColour
= m_currentColour
;
1084 m_currentColour
= m_textForegroundColour
;
1085 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1086 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1087 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1088 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1089 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1091 if (!sameColour
|| !GET_OPTIMIZATION
)
1093 int pixel
= CalculatePixel(m_textForegroundColour
,
1094 m_currentColour
, false);
1096 // Set the GC to the required colour
1099 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1100 if (m_window
&& m_window
->GetBackingPixmap())
1101 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1105 m_textForegroundColour
= oldPenColour
;
1108 // We need to add the ascent, not the whole height, since X draws at the
1109 // point above the descender.
1112 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1113 (XChar2b
*)(char*) (const char*) text
, slen
);
1116 #if wxMOTIF_NEW_FONT_HANDLING
1117 XFontSet fset
= (XFontSet
) m_font
.GetFontSet (m_userScaleY
* m_logicalScaleY
, m_display
);
1118 XmbDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, fset
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1120 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1123 if (m_window
&& m_window
->GetBackingPixmap()) {
1126 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1127 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1128 (XChar2b
*)(char*) (const char*) text
, slen
);
1131 #if wxMOTIF_NEW_FONT_HANDLING
1132 XmbDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), fset
, (GC
) m_gcBacking
,
1133 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1134 wxConstCast(text
.c_str(), char), slen
);
1136 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1137 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1138 wxConstCast(text
.c_str(), char), slen
);
1142 // restore fill style
1143 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, gcV
.fill_style
);
1144 if (m_window
&& m_window
->GetBackingPixmap())
1145 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
,
1146 gcBackingV
.fill_style
);
1149 GetTextExtent (text
, &w
, &h
);
1150 CalcBoundingBox (x
+ w
, y
+ h
);
1151 CalcBoundingBox (x
, y
);
1154 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
,
1159 DrawText(text
, x
, y
);
1163 wxCHECK_RET( Ok(), "invalid dc" );
1165 int oldBackgroundPixel
= -1;
1166 int oldForegroundPixel
= -1;
1167 int foregroundPixel
= -1;
1168 int backgroundPixel
= -1;
1170 if (m_textBackgroundColour
.Ok())
1172 oldBackgroundPixel
= m_backgroundPixel
;
1173 backgroundPixel
= m_textBackgroundColour
.AllocColour(m_display
);
1175 if (m_textForegroundColour
.Ok())
1177 oldForegroundPixel
= m_currentColour
.GetPixel();
1179 if( m_textForegroundColour
.GetPixel() <= -1 )
1180 CalculatePixel( m_textForegroundColour
,
1181 m_textForegroundColour
, true);
1183 foregroundPixel
= m_textForegroundColour
.GetPixel();
1186 // Since X draws from the baseline of the text, must add the text height
1192 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1193 text
, &cx
, &cy
, &ascent
, NULL
);
1195 wxBitmap
src(cx
, cy
);
1197 dc
.SelectObject(src
);
1198 dc
.SetFont(GetFont());
1199 dc
.SetBackground(*wxWHITE_BRUSH
);
1200 dc
.SetBrush(*wxBLACK_BRUSH
);
1202 dc
.DrawText(text
, 0, 0);
1203 dc
.SetFont(wxNullFont
);
1205 // Calculate the size of the rotated bounding box.
1206 double dx
= cos(angle
/ 180.0 * M_PI
);
1207 double dy
= sin(angle
/ 180.0 * M_PI
);
1208 double x4
= cy
* dy
;
1209 double y4
= cy
* dx
;
1210 double x3
= cx
* dx
;
1211 double y3
= -cx
* dy
;
1212 double x2
= x3
+ x4
;
1213 double y2
= y3
+ y4
;
1217 // Create image from the source bitmap after writing the text into it.
1218 wxImage image
= src
.ConvertToImage();
1220 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1221 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1222 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1223 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1225 bool lastFore
= false, lastBack
= false;
1227 // This rotates counterclockwise around the top left corner.
1228 for (int rx
= minx
; rx
< maxx
; rx
++)
1230 for (int ry
= miny
; ry
< maxy
; ry
++)
1232 // transform dest coords to source coords
1233 int sx
= (int) (rx
* dx
- ry
* dy
+ 0.5);
1234 int sy
= - (int) (-ry
* dx
- rx
* dy
+ 0.5);
1235 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1237 bool textPixel
= image
.GetRed(sx
, sy
) == 0;
1239 if (!textPixel
&& m_backgroundMode
!= wxSOLID
)
1242 wxCoord ox
= (wxCoord
) (x1
+ rx
),
1243 oy
= (wxCoord
) (y1
+ ry
);
1244 // draw black pixels, ignore white ones (i.e. transparent b/g)
1245 if (textPixel
&& !lastFore
)
1247 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1252 else if (!textPixel
&& !lastBack
)
1254 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1260 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
,
1261 (GC
) m_gc
, XLOG2DEV (ox
), YLOG2DEV (oy
));
1262 if (m_window
&& m_window
->GetBackingPixmap())
1263 XDrawPoint ((Display
*) m_display
,
1264 (Pixmap
) m_window
->GetBackingPixmap(),
1266 XLOG2DEV_2 (ox
), YLOG2DEV_2 (oy
));
1271 if (oldBackgroundPixel
> -1)
1273 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1274 if (m_window
&& m_window
->GetBackingPixmap())
1275 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1276 oldBackgroundPixel
);
1278 if (oldForegroundPixel
> -1)
1280 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1281 if (m_window
&& m_window
->GetBackingPixmap())
1282 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1283 oldForegroundPixel
);
1286 CalcBoundingBox (minx
, miny
);
1287 CalcBoundingBox (maxx
, maxy
);
1290 bool wxWindowDC::CanGetTextExtent() const
1295 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1296 wxCoord
*descent
, wxCoord
*externalLeading
,
1297 wxFont
*font
) const
1299 wxCHECK_RET( Ok(), "invalid dc" );
1301 const wxFont
* theFont
= font
? font
: &m_font
;
1305 // TODO: this should be an error log function
1306 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1308 if (width
) *width
= -1;
1309 if (height
) *height
= -1;
1313 wxGetTextExtent(m_display
, *theFont
, m_userScaleY
* m_logicalScaleY
,
1314 string
, width
, height
, NULL
, descent
);
1316 if (width
) *width
= XDEV2LOGREL (*width
);
1317 if (height
) *height
= YDEV2LOGREL (*height
);
1318 if (externalLeading
)
1319 *externalLeading
= 0;
1322 wxCoord
wxWindowDC::GetCharWidth() const
1324 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1325 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1329 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1330 "x", &width
, NULL
, NULL
, NULL
);
1332 return XDEV2LOGREL(width
);
1335 wxCoord
wxWindowDC::GetCharHeight() const
1337 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1338 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1342 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1343 "x", NULL
, &height
, NULL
, NULL
);
1345 return XDEV2LOGREL(height
);
1348 void wxWindowDC::DoGetSize( int *width
, int *height
) const
1354 if( m_window
->GetBackingPixmap() )
1356 w
= m_window
->GetPixmapWidth();
1357 h
= m_window
->GetPixmapHeight();
1360 m_window
->GetSize( &w
, &h
);
1363 if( width
) *width
= w
;
1364 if( height
) *height
= h
;
1367 void wxWindowDC::Clear()
1369 wxCHECK_RET( Ok(), "invalid dc" );
1371 wxRect
rect( GetSize() );
1375 void wxWindowDC::Clear(const wxRect
& rect
)
1377 wxCHECK_RET( Ok(), "invalid dc" );
1379 int x
= rect
.x
; int y
= rect
.y
;
1380 int w
= rect
.width
; int h
= rect
.height
;
1382 wxBrush saveBrush
= m_brush
;
1383 SetBrush (m_backgroundBrush
);
1385 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1388 if (m_window
&& m_window
->GetBackingPixmap())
1389 XFillRectangle ((Display
*) m_display
,
1390 (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1393 m_brush
= saveBrush
;
1396 void wxWindowDC::SetFont( const wxFont
&font
)
1398 wxCHECK_RET( Ok(), "invalid dc" );
1407 #if !wxMOTIF_NEW_FONT_HANDLING
1408 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1410 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1411 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1413 if (m_window
&& m_window
->GetBackingPixmap())
1414 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1418 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel
)
1420 if (m_logicalFunction
== wxXOR
)
1423 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1424 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1425 pixel
^ values
.background
);
1426 if (m_window
&& m_window
->GetBackingPixmap())
1427 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1428 pixel
^ values
.background
);
1432 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1433 if (m_window
&& m_window
->GetBackingPixmap())
1434 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1438 int wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1439 bool roundToWhite
) const
1441 const unsigned char wp
= (unsigned char)255;
1444 if(!m_colour
) // Mono display
1446 unsigned char red
= colour
.Red ();
1447 unsigned char blue
= colour
.Blue ();
1448 unsigned char green
= colour
.Green ();
1450 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1451 // not black and roundToWhite was specified
1452 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1455 pixel
= (int)WhitePixel((Display
*) m_display
,
1456 DefaultScreen((Display
*) m_display
));
1457 curCol
.SetPixel(pixel
);
1458 colour
.SetPixel(pixel
);
1463 pixel
= (int)BlackPixel((Display
*) m_display
,
1464 DefaultScreen((Display
*) m_display
));
1465 curCol
.SetPixel(pixel
);
1466 colour
.SetPixel(pixel
);
1472 pixel
= colour
.AllocColour((Display
*) m_display
);
1473 curCol
.SetPixel(pixel
);
1479 void wxWindowDC::SetPen( const wxPen
&pen
)
1481 wxCHECK_RET( Ok(), "invalid dc" );
1487 wxBitmap oldStipple
= m_currentStipple
;
1488 int oldStyle
= m_currentStyle
;
1489 int oldFill
= m_currentFill
;
1490 int old_pen_width
= m_currentPenWidth
;
1491 int old_pen_join
= m_currentPenJoin
;
1492 int old_pen_cap
= m_currentPenCap
;
1493 int old_pen_nb_dash
= m_currentPenDashCount
;
1494 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1496 wxColour oldPenColour
= m_currentColour
;
1497 m_currentColour
= m_pen
.GetColour ();
1498 m_currentStyle
= m_pen
.GetStyle ();
1499 m_currentFill
= m_pen
.GetStyle (); // TODO?
1500 m_currentPenWidth
= m_pen
.GetWidth ();
1501 m_currentPenJoin
= m_pen
.GetJoin ();
1502 m_currentPenCap
= m_pen
.GetCap ();
1503 m_currentPenDashCount
= m_pen
.GetDashCount();
1504 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1506 if (m_currentStyle
== wxSTIPPLE
)
1507 m_currentStipple
= * m_pen
.GetStipple ();
1509 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1510 oldFill
== m_currentFill
&&
1511 old_pen_join
== m_currentPenJoin
&&
1512 old_pen_cap
== m_currentPenCap
&&
1513 old_pen_nb_dash
== m_currentPenDashCount
&&
1514 old_pen_dash
== m_currentPenDash
&&
1515 old_pen_width
== m_currentPenWidth
);
1517 bool sameColour
= (oldPenColour
.Ok () &&
1518 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1519 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1520 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1521 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1523 if (!sameStyle
|| !GET_OPTIMIZATION
)
1525 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1526 if (scaled_width
< 0)
1532 static const wxX11Dash dotted
[] = {2, 5};
1533 static const wxX11Dash short_dashed
[] = {4, 4};
1534 static const wxX11Dash long_dashed
[] = {4, 8};
1535 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1537 // We express dash pattern in pen width unit, so we are
1538 // independent of zoom factor and so on...
1540 const wxX11Dash
*req_dash
;
1542 switch (m_pen
.GetStyle ())
1545 req_nb_dash
= m_currentPenDashCount
;
1546 req_dash
= m_currentPenDash
;
1547 style
= LineOnOffDash
;
1552 style
= LineOnOffDash
;
1556 req_dash
= short_dashed
;
1557 style
= LineOnOffDash
;
1561 req_dash
= long_dashed
;
1562 style
= LineOnOffDash
;
1566 req_dash
= dotted_dashed
;
1567 style
= LineOnOffDash
;
1574 req_dash
= (wxX11Dash
*)NULL
;
1578 if (req_dash
&& req_nb_dash
)
1580 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1583 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1584 for (int i
= 0; i
< req_nb_dash
; i
++)
1585 real_req_dash
[i
] = (wxX11Dash
)(req_dash
[i
] * factor
);
1586 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1588 if (m_window
&& m_window
->GetBackingPixmap())
1589 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1590 delete[]real_req_dash
;
1594 // No Memory. We use non-scaled dash pattern...
1595 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1597 if (m_window
&& m_window
->GetBackingPixmap())
1598 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1602 switch (m_pen
.GetCap ())
1604 case wxCAP_PROJECTING
:
1605 cap
= CapProjecting
;
1612 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1616 switch (m_pen
.GetJoin ())
1630 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1632 if (m_window
&& m_window
->GetBackingPixmap())
1633 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1636 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1640 oldStipple
= wxNullBitmap
; // For later reset!!
1642 switch (m_currentFill
)
1644 case wxBDIAGONAL_HATCH
:
1645 if (bdiag
== (Pixmap
) 0)
1646 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1647 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1648 bdiag_bits
, bdiag_width
, bdiag_height
);
1651 case wxFDIAGONAL_HATCH
:
1652 if (fdiag
== (Pixmap
) 0)
1653 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1654 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1655 fdiag_bits
, fdiag_width
, fdiag_height
);
1659 if (cross
== (Pixmap
) 0)
1660 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1661 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1662 cross_bits
, cross_width
, cross_height
);
1665 case wxHORIZONTAL_HATCH
:
1666 if (horiz
== (Pixmap
) 0)
1667 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1668 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1669 horiz_bits
, horiz_width
, horiz_height
);
1672 case wxVERTICAL_HATCH
:
1673 if (verti
== (Pixmap
) 0)
1674 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1675 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1676 verti_bits
, verti_width
, verti_height
);
1679 case wxCROSSDIAG_HATCH
:
1681 if (cdiag
== (Pixmap
) 0)
1682 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1683 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1684 cdiag_bits
, cdiag_width
, cdiag_height
);
1688 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1690 if (m_window
&& m_window
->GetBackingPixmap())
1691 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1693 else if (m_currentStipple
.Ok()
1694 && ((m_currentStipple
!= oldStipple
) || !GET_OPTIMIZATION
))
1696 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetDrawable());
1698 if (m_window
&& m_window
->GetBackingPixmap())
1699 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetDrawable());
1702 if ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
)
1706 if (m_currentFill
== wxSTIPPLE
)
1707 fill_style
= FillStippled
;
1708 else if (IS_HATCH (m_currentFill
))
1709 fill_style
= FillStippled
;
1711 fill_style
= FillSolid
;
1712 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1713 if (m_window
&& m_window
->GetBackingPixmap())
1714 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1717 // must test m_logicalFunction, because it involves background!
1718 if (!sameColour
|| !GET_OPTIMIZATION
1719 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1722 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1723 pixel
= m_backgroundPixel
;
1726 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, false);
1729 // Finally, set the GC to the required colour
1731 SetForegroundPixelWithLogicalFunction(pixel
);
1734 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1739 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1741 wxCHECK_RET( Ok(), "invalid dc" );
1745 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1748 int oldFill
= m_currentFill
;
1749 wxBitmap oldStipple
= m_currentStipple
;
1751 m_autoSetting
|= 0x1;
1753 m_currentFill
= m_brush
.GetStyle ();
1754 if (m_currentFill
== wxSTIPPLE
)
1755 m_currentStipple
= * m_brush
.GetStipple ();
1757 wxColour
oldBrushColour(m_currentColour
);
1758 m_currentColour
= m_brush
.GetColour ();
1760 bool sameColour
= (oldBrushColour
.Ok () &&
1761 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1762 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1763 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1764 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1766 int stippleDepth
= -1;
1768 if ((oldFill
!= m_brush
.GetStyle ()) || !GET_OPTIMIZATION
)
1770 switch (brush
.GetStyle ())
1775 stippleDepth
= m_currentStipple
.GetDepth();
1777 case wxBDIAGONAL_HATCH
:
1778 case wxCROSSDIAG_HATCH
:
1779 case wxFDIAGONAL_HATCH
:
1781 case wxHORIZONTAL_HATCH
:
1782 case wxVERTICAL_HATCH
:
1784 if (stippleDepth
== -1) stippleDepth
= 1;
1786 // Chris Breeze 23/07/97: use background mode to
1787 // determine whether fill style should be solid or
1789 int style
= stippleDepth
== 1 ?
1790 (m_backgroundMode
== wxSOLID
?
1791 FillOpaqueStippled
: FillStippled
) :
1793 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1794 if (m_window
&& m_window
->GetBackingPixmap())
1795 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1800 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1801 if (m_window
&& m_window
->GetBackingPixmap())
1802 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
,
1807 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1811 switch (m_currentFill
)
1813 case wxBDIAGONAL_HATCH
:
1814 if (bdiag
== (Pixmap
) 0)
1815 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1816 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1817 bdiag_bits
, bdiag_width
, bdiag_height
);
1820 case wxFDIAGONAL_HATCH
:
1821 if (fdiag
== (Pixmap
) 0)
1822 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1823 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1824 fdiag_bits
, fdiag_width
, fdiag_height
);
1828 if (cross
== (Pixmap
) 0)
1829 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1830 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1831 cross_bits
, cross_width
, cross_height
);
1834 case wxHORIZONTAL_HATCH
:
1835 if (horiz
== (Pixmap
) 0)
1836 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1837 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1838 horiz_bits
, horiz_width
, horiz_height
);
1841 case wxVERTICAL_HATCH
:
1842 if (verti
== (Pixmap
) 0)
1843 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1844 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1845 verti_bits
, verti_width
, verti_height
);
1848 case wxCROSSDIAG_HATCH
:
1850 if (cdiag
== (Pixmap
) 0)
1851 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1852 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1853 cdiag_bits
, cdiag_width
, cdiag_height
);
1857 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1859 if (m_window
&& m_window
->GetBackingPixmap())
1860 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1862 // X can forget the stipple value when resizing a window (apparently)
1863 // so always set the stipple.
1864 else if (m_currentFill
!= wxSOLID
&& m_currentFill
!= wxTRANSPARENT
&&
1865 m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1867 if (m_currentStipple
.GetDepth() == 1)
1869 XSetStipple ((Display
*) m_display
, (GC
) m_gc
,
1870 (Pixmap
) m_currentStipple
.GetDrawable());
1871 if (m_window
&& m_window
->GetBackingPixmap())
1872 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
,
1873 (Pixmap
) m_currentStipple
.GetDrawable());
1877 XSetTile ((Display
*) m_display
, (GC
) m_gc
,
1878 (Pixmap
) m_currentStipple
.GetDrawable());
1879 if (m_window
&& m_window
->GetBackingPixmap())
1880 XSetTile ((Display
*) m_display
,(GC
) m_gcBacking
,
1881 (Pixmap
) m_currentStipple
.GetDrawable());
1885 // must test m_logicalFunction, because it involves background!
1886 if (!sameColour
|| !GET_OPTIMIZATION
|| m_logicalFunction
== wxXOR
)
1888 int pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, true);
1891 SetForegroundPixelWithLogicalFunction(pixel
);
1894 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1897 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1899 wxCHECK_RET( Ok(), "invalid dc" );
1901 m_backgroundBrush
= brush
;
1903 if (!m_backgroundBrush
.Ok())
1906 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1908 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1909 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1910 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
1911 if (m_window
&& m_window
->GetBackingPixmap())
1912 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1916 void wxWindowDC::SetLogicalFunction( int function
)
1918 wxCHECK_RET( Ok(), "invalid dc" );
1923 if (m_logicalFunction
== function
)
1929 x_function
= GXclear
;
1935 x_function
= GXinvert
;
1938 x_function
= GXorReverse
;
1941 x_function
= GXandReverse
;
1950 x_function
= GXandInverted
;
1953 x_function
= GXnoop
;
1959 x_function
= GXequiv
;
1962 x_function
= GXcopyInverted
;
1965 x_function
= GXorInverted
;
1968 x_function
= GXnand
;
1975 x_function
= GXcopy
;
1979 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1980 if (m_window
&& m_window
->GetBackingPixmap())
1981 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1983 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1984 /* MATTHEW: [9] Need to redo pen simply */
1985 m_autoSetting
|= 0x2;
1987 m_logicalFunction
= function
;
1991 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1993 wxCHECK_RET( Ok(), "invalid dc" );
1995 m_textForegroundColour
= col
;
1998 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2000 wxCHECK_RET( Ok(), "invalid dc" );
2002 m_textBackgroundColour
= col
;
2005 void wxWindowDC::SetBackgroundMode( int mode
)
2007 m_backgroundMode
= mode
;
2010 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2015 /* Use GetXColormap */
2016 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2017 (Colormap
) palette
.GetXColormap());
2019 /* Use wxGetMainColormap */
2020 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2021 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2025 static void wxCopyRegion( WXRegion src
, WXRegion
& dst
)
2028 dst
= XCreateRegion();
2029 XUnionRegion( (Region
)src
, (Region
)src
, (Region
)dst
);
2032 // Helper function; userRegion is the region set by calling SetClippingRegion
2033 void wxWindowDC::SetDCClipping( WXRegion userRegion
)
2035 bool hasUpdateRegion
= m_window
&& m_window
->GetUpdateRegion().Ok();
2036 // this means that we should start the clip region from scratch,
2037 // or from the update region, if any
2041 XDestroyRegion( (Region
)m_clipRegion
);
2042 m_clipRegion
= (WXRegion
)NULL
;
2044 if( hasUpdateRegion
)
2045 wxCopyRegion( m_window
->GetUpdateRegion().GetX11Region(),
2048 // intersect the user region, if any, with the
2049 // exisiting clip region
2050 else // if( userRegion )
2053 wxCopyRegion( userRegion
, m_clipRegion
);
2055 XIntersectRegion( (Region
)m_clipRegion
,
2056 (Region
)userRegion
, (Region
)m_clipRegion
);
2060 XSetRegion( (Display
*)m_display
, (GC
)m_gc
, (Region
)m_clipRegion
);
2062 XSetClipMask( (Display
*)m_display
, (GC
)m_gc
, None
);
2065 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
,
2066 wxCoord width
, wxCoord height
)
2068 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2070 wxRegion
temp(x
, y
, width
, height
);
2072 SetDCClipping(temp
.GetX11Region());
2074 // Needs to work differently for Pixmap: without this,
2075 // there's a nasty (Display*) m_display bug. 8/12/94
2076 if (m_window
&& m_window
->GetBackingPixmap())
2078 XRectangle rects
[1];
2079 rects
[0].x
= (short)XLOG2DEV_2(x
);
2080 rects
[0].y
= (short)YLOG2DEV_2(y
);
2081 rects
[0].width
= (unsigned short)XLOG2DEVREL(width
);
2082 rects
[0].height
= (unsigned short)YLOG2DEVREL(height
);
2083 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2084 0, 0, rects
, 1, Unsorted
);
2088 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2090 wxRect box
= region
.GetBox();
2092 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2094 SetDCClipping(region
.GetX11Region());
2096 // Needs to work differently for Pixmap: without this,
2097 // there's a nasty (Display*) m_display bug. 8/12/94
2098 if (m_window
&& m_window
->GetBackingPixmap())
2100 XRectangle rects
[1];
2101 rects
[0].x
= (short)XLOG2DEV_2(box
.x
);
2102 rects
[0].y
= (short)YLOG2DEV_2(box
.y
);
2103 rects
[0].width
= (unsigned short)XLOG2DEVREL(box
.width
);
2104 rects
[0].height
= (unsigned short)YLOG2DEVREL(box
.height
);
2105 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2106 0, 0, rects
, 1, Unsorted
);
2111 void wxWindowDC::DestroyClippingRegion()
2113 wxDC::DestroyClippingRegion();
2115 SetDCClipping(NULL
);
2117 if (m_window
&& m_window
->GetBackingPixmap())
2118 XSetClipMask ((Display
*) m_display
, (GC
) m_gcBacking
, None
);
2121 // Resolution in pixels per logical inch
2122 wxSize
wxWindowDC::GetPPI() const
2125 return wxSize(100, 100);
2128 int wxWindowDC::GetDepth() const
2137 // ----------------------------------------------------------------------------
2139 // ----------------------------------------------------------------------------
2141 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2143 // Set the clipping region.to the update region
2144 SetDCClipping((WXRegion
)NULL
);
2147 wxPaintDC::~wxPaintDC()
2150 m_window
->ClearUpdateRegion();
2151 SetDCClipping((WXRegion
)NULL
);
2154 // ----------------------------------------------------------------------------
2155 // private functions
2156 // ----------------------------------------------------------------------------
2159 Used when copying between drawables on different (Display*) m_displays. Not
2160 very fast, but better than giving up.
2163 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2164 Drawable src
, Drawable dest
,
2167 unsigned int w
, unsigned int h
,
2168 int destx
, int desty
,
2169 bool more
, XImage
**cache
)
2171 XImage
*image
, *destimage
;
2172 Colormap destcm
, srccm
;
2173 static const int CACHE_SIZE
= 256;
2176 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2177 int k
, cache_pos
, all_cache
;
2179 if (!cache
|| !*cache
)
2180 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2184 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2186 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2187 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2192 for (i
= 0; i
< w
; i
++)
2193 for (j
= 0; j
< h
; j
++) {
2194 unsigned long pixel
;
2197 pixel
= XGetPixel(image
, i
, j
);
2198 for (k
= cache_pos
; k
--; )
2199 if (cachesrc
[k
] == pixel
) {
2200 pixel
= cachedest
[k
];
2204 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2205 if (cachesrc
[k
] == pixel
) {
2206 pixel
= cachedest
[k
];
2210 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2211 XQueryColor(src_display
, srccm
, &xcol
);
2212 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2214 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2216 if (++cache_pos
>= CACHE_SIZE
) {
2222 XPutPixel(destimage
, i
, j
, pixel
);
2225 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2226 XDestroyImage(destimage
);
2231 XDestroyImage(image
);
2236 /* Helper function for 16-bit fonts */
2237 static int str16len(const char *s
)
2241 while (s
[0] && s
[1]) {