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"
48 #include "wx/dcmemory.h"
54 #pragma message disable nosimpint
58 #pragma message enable nosimpint
61 #include "wx/motif/private.h"
64 #include <float.h> // for M_PI
74 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
76 // ----------------------------------------------------------------------------
78 // ----------------------------------------------------------------------------
80 // Fudge factor (VZ: what??)
83 // ----------------------------------------------------------------------------
85 // ----------------------------------------------------------------------------
87 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
88 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
89 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
91 #define IS_HATCH(s) ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH)
93 // FIXME: left over after removal of wxDC::GetOptimization()
94 #define GET_OPTIMIZATION false
96 // ----------------------------------------------------------------------------
98 // ----------------------------------------------------------------------------
100 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
101 Drawable src
, Drawable dest
,
104 unsigned int w
, unsigned int h
,
105 int destx
, int desty
,
106 bool more
, XImage
**cache
);
108 // ============================================================================
110 // ============================================================================
113 * compare two doubles and return the larger rounded
116 static int roundmax(double a
, double b
)
118 return (int)((a
> b
? a
: b
) + 0.5);
122 * compare two doubles and return the smaller rounded
125 static int roundmin(double a
, double b
)
127 return (int)((a
< b
? a
: b
) - 0.5);
131 // ----------------------------------------------------------------------------
133 // ----------------------------------------------------------------------------
135 void wxWindowDC::Init()
138 m_gcBacking
= (WXGC
) 0;
140 m_backgroundPixel
= -1;
141 m_currentPenWidth
= 1;
142 m_currentPenJoin
= -1;
143 m_currentPenDashCount
= -1;
144 m_currentPenDash
= (wxX11Dash
*) NULL
;
147 m_colour
= wxColourDisplay();
148 m_display
= (WXDisplay
*) NULL
;
149 m_pixmap
= (WXPixmap
) 0;
152 m_clipRegion
= (WXRegion
) 0;
155 wxWindowDC::wxWindowDC()
160 wxWindowDC::wxWindowDC( wxWindow
*window
)
162 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
167 m_font
= window
->GetFont();
170 m_display
= window
->GetXDisplay();
171 m_pixmap
= window
->GetXWindow();
172 Display
* display
= (Display
*) m_display
;
174 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
177 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
178 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
179 gcvalues
.graphics_exposures
= False
;
180 gcvalues
.subwindow_mode
= IncludeInferiors
;
181 gcvalues
.line_width
= 1;
182 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
183 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
186 if (m_window
->GetBackingPixmap())
188 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
189 DefaultScreen (display
)),
190 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
194 m_backgroundPixel
= gcvalues
.background
;
196 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
199 wxWindowDC::~wxWindowDC()
202 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
206 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
207 m_gcBacking
= (WXGC
) 0;
210 XDestroyRegion ((Region
) m_clipRegion
);
211 m_clipRegion
= (WXRegion
) 0;
214 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
215 const wxColour
& col
, int style
);
217 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
218 const wxColour
& col
, int style
)
220 return wxDoFloodFill(this, x
, y
, col
, style
);
223 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
225 // Generic (and therefore rather inefficient) method.
226 // Could be improved.
228 wxBitmap
bitmap(1, 1);
229 memdc
.SelectObject(bitmap
);
230 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
231 memdc
.SelectObject(wxNullBitmap
);
232 wxImage image
= bitmap
.ConvertToImage();
233 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
237 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
239 wxCHECK_RET( Ok(), "invalid dc" );
241 int x1d
, y1d
, x2d
, y2d
;
251 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
253 if (m_window
&& m_window
->GetBackingPixmap())
254 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
255 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
256 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
258 CalcBoundingBox(x1
, y1
);
259 CalcBoundingBox(x2
, y2
);
262 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
264 wxCHECK_RET( Ok(), "invalid dc" );
269 int xx
= XLOG2DEV (x
);
270 int yy
= YLOG2DEV (y
);
272 wxDisplaySize (&ww
, &hh
);
273 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
275 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
278 if (m_window
&& m_window
->GetBackingPixmap())
282 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
285 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
291 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
293 wxCHECK_RET( Ok(), "invalid dc" );
295 int xx1
= XLOG2DEV (x1
);
296 int yy1
= YLOG2DEV (y1
);
297 int xx2
= XLOG2DEV (x2
);
298 int yy2
= YLOG2DEV (y2
);
299 int xxc
= XLOG2DEV (xc
);
300 int yyc
= YLOG2DEV (yc
);
301 int xxc_2
= XLOG2DEV_2 (xc
);
302 int yyc_2
= YLOG2DEV_2 (yc
);
304 wxCoord dx
= xx1
- xxc
;
305 wxCoord dy
= yy1
- yyc
;
306 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
307 wxCoord r
= (wxCoord
) radius
;
309 double radius1
, radius2
;
311 if (xx1
== xx2
&& yy1
== yy2
)
316 else if (radius
== 0.0)
317 radius1
= radius2
= 0.0;
326 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
334 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
338 int alpha1
= (int) radius1
;
339 int alpha2
= (int) (radius2
- radius1
);
342 while (alpha2
> 360 * 64)
345 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
348 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
349 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
351 if (m_window
&& m_window
->GetBackingPixmap())
352 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
353 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
357 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
361 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
362 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
364 if (m_window
&& m_window
->GetBackingPixmap())
365 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
366 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
368 CalcBoundingBox (x1
, y1
);
369 CalcBoundingBox (x2
, y2
);
372 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
374 wxCHECK_RET( Ok(), "invalid dc" );
380 wd
= XLOG2DEVREL(width
);
381 hd
= YLOG2DEVREL(height
);
383 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
384 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
385 int start
= int(sa
*64);
386 int end
= int(ea
*64);
387 if (start
<0) start
+=360*64;
388 if (end
<0) end
+=360*64;
389 if (end
>start
) end
-=start
;
390 else end
+=360*64-start
;
392 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
394 m_autoSetting
= true; // must be reset
397 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
399 if (m_window
&& m_window
->GetBackingPixmap())
400 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
401 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
404 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
408 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
409 if (m_window
&& m_window
->GetBackingPixmap())
410 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
411 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
413 CalcBoundingBox (x
, y
);
414 CalcBoundingBox (x
+ width
, y
+ height
);
417 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
419 wxCHECK_RET( Ok(), "invalid dc" );
421 if (m_pen
.Ok() && m_autoSetting
)
424 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
425 if (m_window
&& m_window
->GetBackingPixmap())
426 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
428 CalcBoundingBox (x
, y
);
431 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
433 wxCHECK_RET( Ok(), "invalid dc" );
435 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
440 XPoint
*xpoints
= new XPoint
[n
];
443 for (i
= 0; i
< n
; i
++)
445 xpoints
[i
].x
= (short)XLOG2DEV (points
[i
].x
+ xoffset
);
446 xpoints
[i
].y
= (short)YLOG2DEV (points
[i
].y
+ yoffset
);
448 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
450 if (m_window
&& m_window
->GetBackingPixmap())
452 for (i
= 0; i
< n
; i
++)
454 xpoints
[i
].x
= (short)XLOG2DEV_2 (points
[i
].x
+ xoffset
);
455 xpoints
[i
].y
= (short)YLOG2DEV_2 (points
[i
].y
+ yoffset
);
457 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
463 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
464 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
466 wxCHECK_RET( Ok(), "invalid dc" );
468 XPoint
*xpoints1
= new XPoint
[n
+ 1];
469 XPoint
*xpoints2
= new XPoint
[n
+ 1];
471 for (i
= 0; i
< n
; i
++)
473 xpoints1
[i
].x
= (short)XLOG2DEV (points
[i
].x
+ xoffset
);
474 xpoints1
[i
].y
= (short)YLOG2DEV (points
[i
].y
+ yoffset
);
475 xpoints2
[i
].x
= (short)XLOG2DEV_2 (points
[i
].x
+ xoffset
);
476 xpoints2
[i
].y
= (short)YLOG2DEV_2 (points
[i
].y
+ yoffset
);
477 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
480 // Close figure for XDrawLines (not needed for XFillPolygon)
481 xpoints1
[i
].x
= xpoints1
[0].x
;
482 xpoints1
[i
].y
= xpoints1
[0].y
;
483 xpoints2
[i
].x
= xpoints2
[0].x
;
484 xpoints2
[i
].y
= xpoints2
[0].y
;
486 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
489 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
490 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
491 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
492 if (m_window
&& m_window
->GetBackingPixmap())
494 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
495 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
496 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
497 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
501 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
505 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
507 if (m_window
&& m_window
->GetBackingPixmap())
508 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
515 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
517 wxCHECK_RET( Ok(), "invalid dc" );
519 int xd
, yd
, wfd
, hfd
, wd
, hd
;
523 wfd
= XLOG2DEVREL(width
);
525 hfd
= YLOG2DEVREL(height
);
528 if (wfd
== 0 || hfd
== 0) return;
529 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
530 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
532 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
535 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
537 if (m_window
&& m_window
->GetBackingPixmap())
538 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
539 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
543 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
547 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
549 if (m_window
&& m_window
->GetBackingPixmap())
550 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
551 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
554 CalcBoundingBox (x
, y
);
555 CalcBoundingBox (x
+ width
, y
+ height
);
558 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
560 wxCHECK_RET( Ok(), "invalid dc" );
562 // If radius is negative, it's a proportion of the smaller dimension.
564 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
566 int xd
= XLOG2DEV (x
);
567 int yd
= YLOG2DEV (y
);
568 int rd
= XLOG2DEVREL ((long) radius
);
569 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
570 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
575 // If radius is zero use DrawRectangle() instead to avoid
576 // X drawing errors with small radii
579 DrawRectangle( x
, y
, width
, height
);
583 // Draw nothing if transformed w or h is 0
584 if (wd
== 0 || hd
== 0) return;
586 // CMB: adjust size if outline is drawn otherwise the result is
587 // 1 pixel too wide and high
588 if (m_pen
.GetStyle() != wxTRANSPARENT
)
594 // CMB: ensure dd is not larger than rectangle otherwise we
595 // get an hour glass shape
596 if (rw_d
> wd
) rw_d
= wd
;
597 if (rw_d
> hd
) rw_d
= hd
;
600 // For backing pixmap
601 int xd2
= XLOG2DEV_2 (x
);
602 int yd2
= YLOG2DEV_2 (y
);
603 int rd2
= XLOG2DEVREL ((long) radius
);
604 int wd2
= XLOG2DEVREL (width
) ;
605 int hd2
= YLOG2DEVREL (height
) ;
610 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
614 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
616 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
619 // Arcs start from 3 o'clock, positive angles anticlockwise
621 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
622 rw_d
, rh_d
, 90 * 64, 90 * 64);
624 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
625 // rw_d, rh_d, 0, 90 * 64);
626 rw_d
, rh_d
, 0, 91 * 64);
628 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
630 // rw_d, rh_d, 270 * 64, 90 * 64);
631 rw_d
, rh_d
, 269 * 64, 92 * 64);
633 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
634 rw_d
, rh_d
, 180 * 64, 90 * 64);
636 if (m_window
&& m_window
->GetBackingPixmap())
638 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
639 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
640 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
641 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
643 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
644 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
645 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
646 xd2
+ wd2
- rw_d2
, yd2
,
647 // rw_d2, rh_d2, 0, 90 * 64);
648 rw_d2
, rh_d2
, 0, 91 * 64);
649 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
652 // rw_d2, rh_d2, 270 * 64, 90 * 64);
653 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
654 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
655 xd2
, yd2
+ hd2
- rh_d2
,
656 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
660 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
663 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
664 xd
+ wd
- rd
+ 1, yd
);
665 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
666 xd
+ wd
- rd
, yd
+ hd
);
668 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
670 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
671 xd
+ wd
, yd
+ hd
- rd
+ 1);
672 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
673 rw_d
, rh_d
, 90 * 64, 90 * 64);
674 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
675 // rw_d, rh_d, 0, 90 * 64);
676 rw_d
, rh_d
, 0, 91 * 64);
677 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
679 rw_d
, rh_d
, 269 * 64, 92 * 64);
680 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
681 rw_d
, rh_d
, 180 * 64, 90 * 64);
683 if (m_window
&& m_window
->GetBackingPixmap())
685 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
687 xd2
+ wd2
- rd2
+ 1, yd2
);
688 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
689 xd2
+ rd2
, yd2
+ hd2
,
690 xd2
+ wd2
- rd2
, yd2
+ hd2
);
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
694 xd2
, yd2
+ hd2
- rd2
);
695 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
696 xd2
+ wd2
, yd2
+ rd2
,
697 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
698 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
700 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
701 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
702 xd2
+ wd2
- rw_d2
, yd2
,
703 // rw_d2, rh_d2, 0, 90 * 64);
704 rw_d2
, rh_d2
, 0, 91 * 64);
705 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
708 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
709 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
710 xd2
, yd2
+ hd2
- rh_d2
,
711 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
714 CalcBoundingBox (x
, y
);
715 CalcBoundingBox (x
+ width
, y
+ height
);
718 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
720 wxCHECK_RET( Ok(), "invalid dc" );
722 // Check for negative width and height
735 static const int angle
= 23040;
741 wd
= XLOG2DEVREL(width
) ;
742 hd
= YLOG2DEVREL(height
) ;
744 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
747 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
748 if (m_window
&& m_window
->GetBackingPixmap())
749 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
750 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
751 XLOG2DEVREL (width
) - WX_GC_CF
,
752 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
755 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
759 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
760 if (m_window
&& m_window
->GetBackingPixmap())
761 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
762 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
763 XLOG2DEVREL (width
) - WX_GC_CF
,
764 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
766 CalcBoundingBox (x
, y
);
767 CalcBoundingBox (x
+ width
, y
+ height
);
771 bool wxWindowDC::CanDrawBitmap() const
773 wxCHECK_MSG( Ok(), false, "invalid dc" );
778 // TODO: use scaled Blit e.g. as per John Price's implementation
779 // in Contrib/Utilities
780 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
781 wxCoord width
, wxCoord height
,
782 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
783 int rop
, bool useMask
,
784 wxCoord xsrcMask
, wxCoord ysrcMask
)
786 wxCHECK_MSG( Ok(), false, "invalid dc" );
788 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
790 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
792 // Be sure that foreground pixels (1) of the Icon will be painted with
793 // foreground colour. [m_textForegroundColour] Background pixels (0)
794 // will be painted with backgound colour (m_textBackgroundColour)
795 // Using ::SetPen is horribly slow, so avoid doing it
796 WXPixel oldBackgroundPixel
= -1;
797 WXPixel oldForegroundPixel
= -1;
799 if (m_textBackgroundColour
.Ok())
801 oldBackgroundPixel
= m_backgroundPixel
;
802 WXPixel pixel
= m_textBackgroundColour
.AllocColour(m_display
);
804 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
805 if (m_window
&& m_window
->GetBackingPixmap())
806 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
809 if (m_textForegroundColour
.Ok())
811 oldForegroundPixel
= m_currentColour
.GetPixel();
813 if( m_textForegroundColour
.GetPixel() <= -1 )
814 CalculatePixel( m_textForegroundColour
,
815 m_textForegroundColour
, true);
817 WXPixel pixel
= m_textForegroundColour
.GetPixel();
819 SetForegroundPixelWithLogicalFunction(pixel
);
822 // Do bitmap scaling if necessary
824 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
825 Pixmap sourcePixmap
= (Pixmap
) NULL
;
826 double scaleX
, scaleY
;
827 GetUserScale(& scaleX
, & scaleY
);
830 /* TODO: use the mask origin when drawing transparently */
831 if (xsrcMask
== -1 && ysrcMask
== -1)
833 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
836 // Sorry, can't scale masks just yet
837 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
839 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
840 wxBitmap
& bitmap
= memDC
->GetBitmap();
842 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
844 wxImage image
= bitmap
.ConvertToImage();
847 sourcePixmap
= (Pixmap
) bitmap
.GetDrawable();
851 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
852 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
854 image
= image
.Scale(scaledW
, scaledH
);
855 scaledBitmap
= new wxBitmap(image
);
856 sourcePixmap
= (Pixmap
) scaledBitmap
->GetDrawable();
860 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
862 if (m_pixmap
&& sourcePixmap
)
865 int orig
= m_logicalFunction
;
867 SetLogicalFunction (rop
);
869 if (m_display
!= sourceDC
->m_display
)
871 XImage
*cache
= NULL
;
873 if (m_window
&& m_window
->GetBackingPixmap())
874 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
875 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
877 source
->LogicalToDeviceX (xsrc
),
878 source
->LogicalToDeviceY (ysrc
),
879 source
->LogicalToDeviceXRel(width
),
880 source
->LogicalToDeviceYRel(height
),
881 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
884 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
886 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
887 wxBitmap
& sel
= memDC
->GetBitmap();
888 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
890 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
891 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
895 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
896 source
->LogicalToDeviceX (xsrc
),
897 source
->LogicalToDeviceY (ysrc
),
898 source
->LogicalToDeviceXRel(width
),
899 source
->LogicalToDeviceYRel(height
),
900 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
906 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
907 (Region
) m_clipRegion
);
909 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
911 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
915 { //XGCValues values;
916 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
918 if (m_window
&& m_window
->GetBackingPixmap())
920 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
921 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
923 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
924 source
->LogicalToDeviceX (xsrc
),
925 source
->LogicalToDeviceY (ysrc
),
926 source
->LogicalToDeviceXRel(width
),
927 source
->LogicalToDeviceYRel(height
),
928 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
932 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
933 source
->LogicalToDeviceX (xsrc
),
934 source
->LogicalToDeviceY (ysrc
),
935 source
->LogicalToDeviceXRel(width
),
936 source
->LogicalToDeviceYRel(height
),
937 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
940 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
942 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
943 wxBitmap
& sel
= memDC
->GetBitmap();
944 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetBitmap() )
946 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetBitmap());
947 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
951 // Check if we're copying from a mono bitmap
952 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
953 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
955 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
956 source
->LogicalToDeviceX (xsrc
),
957 source
->LogicalToDeviceY (ysrc
),
958 source
->LogicalToDeviceXRel(width
),
959 source
->LogicalToDeviceYRel(height
),
960 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
964 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
965 source
->LogicalToDeviceX (xsrc
),
966 source
->LogicalToDeviceY (ysrc
),
967 source
->LogicalToDeviceXRel(width
),
968 source
->LogicalToDeviceYRel(height
),
969 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
975 XSetRegion ((Display
*) m_display
, (GC
) m_gc
,
976 (Region
) m_clipRegion
);
978 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
980 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
983 } /* Remote/local (Display*) m_display */
984 CalcBoundingBox (xdest
, ydest
);
985 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
987 SetLogicalFunction(orig
);
991 if (scaledBitmap
) delete scaledBitmap
;
993 if (oldBackgroundPixel
> -1)
995 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
996 if (m_window
&& m_window
->GetBackingPixmap())
997 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1000 if (oldForegroundPixel
> -1)
1002 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1003 if (m_window
&& m_window
->GetBackingPixmap())
1004 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1005 oldForegroundPixel
);
1011 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1013 wxCHECK_RET( Ok(), "invalid dc" );
1015 // Since X draws from the baseline of the text, must add the text height
1019 int slen
= text
.length();
1021 // Set FillStyle, otherwise X will use current stipple!
1022 XGCValues gcV
, gcBackingV
;
1024 XGetGCValues ((Display
*) m_display
, (GC
)m_gc
, GCFillStyle
, &gcV
);
1025 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1026 if (m_window
&& m_window
->GetBackingPixmap())
1028 XGetGCValues ((Display
*) m_display
, (GC
)m_gcBacking
, GCFillStyle
,
1030 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
, FillSolid
);
1034 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1035 text
, &cx
, &cy
, &ascent
, NULL
);
1037 // First draw a rectangle representing the text background, if a text
1038 // background is specified
1039 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1041 wxColour oldPenColour
= m_currentColour
;
1042 m_currentColour
= m_textBackgroundColour
;
1043 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1044 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1045 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1046 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1048 // This separation of the big && test required for gcc2.7/HP UX 9.02
1049 // or pixel value can be corrupted!
1050 sameColour
= (sameColour
&&
1051 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1053 if (!sameColour
|| !GET_OPTIMIZATION
)
1055 WXPixel pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1056 m_currentColour
= m_textBackgroundColour
;
1058 // Set the GC to the required colour
1061 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1062 if (m_window
&& m_window
->GetBackingPixmap())
1063 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1067 m_textBackgroundColour
= oldPenColour
;
1069 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1070 if (m_window
&& m_window
->GetBackingPixmap())
1071 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1072 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1075 // Now set the text foreground and draw the text
1076 if (m_textForegroundColour
.Ok ())
1078 wxColour oldPenColour
= m_currentColour
;
1079 m_currentColour
= m_textForegroundColour
;
1080 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1081 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1082 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1083 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1084 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1086 if (!sameColour
|| !GET_OPTIMIZATION
)
1088 WXPixel pixel
= CalculatePixel(m_textForegroundColour
,
1089 m_currentColour
, false);
1091 // Set the GC to the required colour
1094 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1095 if (m_window
&& m_window
->GetBackingPixmap())
1096 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1100 m_textForegroundColour
= oldPenColour
;
1103 // We need to add the ascent, not the whole height, since X draws at the
1104 // point above the descender.
1107 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1108 (XChar2b
*)(char*) (const char*) text
, slen
);
1111 #if wxMOTIF_NEW_FONT_HANDLING
1112 XFontSet fset
= (XFontSet
) m_font
.GetFontSet (m_userScaleY
* m_logicalScaleY
, m_display
);
1113 XmbDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, fset
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1115 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1118 if (m_window
&& m_window
->GetBackingPixmap()) {
1121 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1122 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1123 (XChar2b
*)(char*) (const char*) text
, slen
);
1126 #if wxMOTIF_NEW_FONT_HANDLING
1127 XmbDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), fset
, (GC
) m_gcBacking
,
1128 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1129 wxConstCast(text
.c_str(), char), slen
);
1131 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1132 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1133 wxConstCast(text
.c_str(), char), slen
);
1137 // restore fill style
1138 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, gcV
.fill_style
);
1139 if (m_window
&& m_window
->GetBackingPixmap())
1140 XSetFillStyle ((Display
*) m_display
, (GC
) m_gcBacking
,
1141 gcBackingV
.fill_style
);
1144 GetTextExtent (text
, &w
, &h
);
1145 CalcBoundingBox (x
+ w
, y
+ h
);
1146 CalcBoundingBox (x
, y
);
1149 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
,
1154 DrawText(text
, x
, y
);
1158 wxCHECK_RET( Ok(), "invalid dc" );
1160 WXPixel oldBackgroundPixel
= -1;
1161 WXPixel oldForegroundPixel
= -1;
1162 WXPixel foregroundPixel
= -1;
1163 WXPixel backgroundPixel
= -1;
1165 if (m_textBackgroundColour
.Ok())
1167 oldBackgroundPixel
= m_backgroundPixel
;
1168 backgroundPixel
= m_textBackgroundColour
.AllocColour(m_display
);
1170 if (m_textForegroundColour
.Ok())
1172 oldForegroundPixel
= m_currentColour
.GetPixel();
1174 if( m_textForegroundColour
.GetPixel() <= -1 )
1175 CalculatePixel( m_textForegroundColour
,
1176 m_textForegroundColour
, true);
1178 foregroundPixel
= m_textForegroundColour
.GetPixel();
1181 // Since X draws from the baseline of the text, must add the text height
1187 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1188 text
, &cx
, &cy
, &ascent
, NULL
);
1190 wxBitmap
src(cx
, cy
);
1192 dc
.SelectObject(src
);
1193 dc
.SetFont(GetFont());
1194 dc
.SetBackground(*wxWHITE_BRUSH
);
1195 dc
.SetBrush(*wxBLACK_BRUSH
);
1197 dc
.DrawText(text
, 0, 0);
1198 dc
.SetFont(wxNullFont
);
1200 // Calculate the size of the rotated bounding box.
1201 double dx
= cos(angle
/ 180.0 * M_PI
);
1202 double dy
= sin(angle
/ 180.0 * M_PI
);
1203 double x4
= cy
* dy
;
1204 double y4
= cy
* dx
;
1205 double x3
= cx
* dx
;
1206 double y3
= -cx
* dy
;
1207 double x2
= x3
+ x4
;
1208 double y2
= y3
+ y4
;
1212 // Create image from the source bitmap after writing the text into it.
1213 wxImage image
= src
.ConvertToImage();
1215 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1216 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1217 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1218 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1220 bool lastFore
= false, lastBack
= false;
1222 // This rotates counterclockwise around the top left corner.
1223 for (int rx
= minx
; rx
< maxx
; rx
++)
1225 for (int ry
= miny
; ry
< maxy
; ry
++)
1227 // transform dest coords to source coords
1228 int sx
= (int) (rx
* dx
- ry
* dy
+ 0.5);
1229 int sy
= - (int) (-ry
* dx
- rx
* dy
+ 0.5);
1230 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1232 bool textPixel
= image
.GetRed(sx
, sy
) == 0;
1234 if (!textPixel
&& m_backgroundMode
!= wxSOLID
)
1237 wxCoord ox
= (wxCoord
) (x1
+ rx
),
1238 oy
= (wxCoord
) (y1
+ ry
);
1239 // draw black pixels, ignore white ones (i.e. transparent b/g)
1240 if (textPixel
&& !lastFore
)
1242 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1247 else if (!textPixel
&& !lastBack
)
1249 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1255 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
,
1256 (GC
) m_gc
, XLOG2DEV (ox
), YLOG2DEV (oy
));
1257 if (m_window
&& m_window
->GetBackingPixmap())
1258 XDrawPoint ((Display
*) m_display
,
1259 (Pixmap
) m_window
->GetBackingPixmap(),
1261 XLOG2DEV_2 (ox
), YLOG2DEV_2 (oy
));
1266 if (oldBackgroundPixel
> -1)
1268 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1269 if (m_window
&& m_window
->GetBackingPixmap())
1270 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1271 oldBackgroundPixel
);
1273 if (oldForegroundPixel
> -1)
1275 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1276 if (m_window
&& m_window
->GetBackingPixmap())
1277 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1278 oldForegroundPixel
);
1281 CalcBoundingBox (minx
, miny
);
1282 CalcBoundingBox (maxx
, maxy
);
1285 bool wxWindowDC::CanGetTextExtent() const
1290 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1291 wxCoord
*descent
, wxCoord
*externalLeading
,
1292 wxFont
*font
) const
1294 wxCHECK_RET( Ok(), "invalid dc" );
1296 const wxFont
* theFont
= font
? font
: &m_font
;
1300 // TODO: this should be an error log function
1301 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1303 if (width
) *width
= -1;
1304 if (height
) *height
= -1;
1308 wxGetTextExtent(m_display
, *theFont
, m_userScaleY
* m_logicalScaleY
,
1309 string
, width
, height
, NULL
, descent
);
1311 if (width
) *width
= XDEV2LOGREL (*width
);
1312 if (height
) *height
= YDEV2LOGREL (*height
);
1313 if (externalLeading
)
1314 *externalLeading
= 0;
1317 wxCoord
wxWindowDC::GetCharWidth() const
1319 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1320 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1324 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1325 "x", &width
, NULL
, NULL
, NULL
);
1327 return XDEV2LOGREL(width
);
1330 wxCoord
wxWindowDC::GetCharHeight() const
1332 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1333 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1337 wxGetTextExtent (m_display
, m_font
, m_userScaleY
* m_logicalScaleY
,
1338 "x", NULL
, &height
, NULL
, NULL
);
1340 return XDEV2LOGREL(height
);
1343 void wxWindowDC::DoGetSize( int *width
, int *height
) const
1349 if( m_window
->GetBackingPixmap() )
1351 w
= m_window
->GetPixmapWidth();
1352 h
= m_window
->GetPixmapHeight();
1355 m_window
->GetSize( &w
, &h
);
1358 if( width
) *width
= w
;
1359 if( height
) *height
= h
;
1362 void wxWindowDC::Clear()
1364 wxCHECK_RET( Ok(), "invalid dc" );
1366 wxRect
rect( GetSize() );
1370 void wxWindowDC::Clear(const wxRect
& rect
)
1372 wxCHECK_RET( Ok(), "invalid dc" );
1374 int x
= rect
.x
; int y
= rect
.y
;
1375 int w
= rect
.width
; int h
= rect
.height
;
1377 wxBrush saveBrush
= m_brush
;
1378 SetBrush (m_backgroundBrush
);
1380 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1383 if (m_window
&& m_window
->GetBackingPixmap())
1384 XFillRectangle ((Display
*) m_display
,
1385 (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1388 m_brush
= saveBrush
;
1391 void wxWindowDC::SetFont( const wxFont
&font
)
1393 wxCHECK_RET( Ok(), "invalid dc" );
1402 #if !wxMOTIF_NEW_FONT_HANDLING
1403 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1405 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1406 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1408 if (m_window
&& m_window
->GetBackingPixmap())
1409 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1413 void wxWindowDC::SetForegroundPixelWithLogicalFunction(WXPixel pixel
)
1415 if (m_logicalFunction
== wxXOR
)
1418 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1419 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1420 pixel
^ values
.background
);
1421 if (m_window
&& m_window
->GetBackingPixmap())
1422 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1423 pixel
^ values
.background
);
1427 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1428 if (m_window
&& m_window
->GetBackingPixmap())
1429 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1433 WXPixel
wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1434 bool roundToWhite
) const
1436 const unsigned char wp
= (unsigned char)255;
1439 if(!m_colour
) // Mono display
1441 unsigned char red
= colour
.Red ();
1442 unsigned char blue
= colour
.Blue ();
1443 unsigned char green
= colour
.Green ();
1445 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1446 // not black and roundToWhite was specified
1447 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1450 pixel
= WhitePixel((Display
*) m_display
,
1451 DefaultScreen((Display
*) m_display
));
1452 curCol
.SetPixel(pixel
);
1453 colour
.SetPixel(pixel
);
1458 pixel
= BlackPixel((Display
*) m_display
,
1459 DefaultScreen((Display
*) m_display
));
1460 curCol
.SetPixel(pixel
);
1461 colour
.SetPixel(pixel
);
1467 pixel
= colour
.AllocColour((Display
*) m_display
);
1468 curCol
.SetPixel(pixel
);
1474 void wxWindowDC::SetPen( const wxPen
&pen
)
1476 wxCHECK_RET( Ok(), "invalid dc" );
1482 wxBitmap oldStipple
= m_currentStipple
;
1483 int oldStyle
= m_currentStyle
;
1484 int oldFill
= m_currentFill
;
1485 int old_pen_width
= m_currentPenWidth
;
1486 int old_pen_join
= m_currentPenJoin
;
1487 int old_pen_cap
= m_currentPenCap
;
1488 int old_pen_nb_dash
= m_currentPenDashCount
;
1489 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1491 wxColour oldPenColour
= m_currentColour
;
1492 m_currentColour
= m_pen
.GetColour ();
1493 m_currentStyle
= m_pen
.GetStyle ();
1494 m_currentFill
= m_pen
.GetStyle (); // TODO?
1495 m_currentPenWidth
= m_pen
.GetWidth ();
1496 m_currentPenJoin
= m_pen
.GetJoin ();
1497 m_currentPenCap
= m_pen
.GetCap ();
1498 m_currentPenDashCount
= m_pen
.GetDashCount();
1499 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1501 if (m_currentStyle
== wxSTIPPLE
)
1502 m_currentStipple
= * m_pen
.GetStipple ();
1504 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1505 oldFill
== m_currentFill
&&
1506 old_pen_join
== m_currentPenJoin
&&
1507 old_pen_cap
== m_currentPenCap
&&
1508 old_pen_nb_dash
== m_currentPenDashCount
&&
1509 old_pen_dash
== m_currentPenDash
&&
1510 old_pen_width
== m_currentPenWidth
);
1512 bool sameColour
= (oldPenColour
.Ok () &&
1513 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1514 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1515 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1516 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1518 if (!sameStyle
|| !GET_OPTIMIZATION
)
1520 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1521 if (scaled_width
< 0)
1527 static const wxX11Dash dotted
[] = {2, 5};
1528 static const wxX11Dash short_dashed
[] = {4, 4};
1529 static const wxX11Dash long_dashed
[] = {4, 8};
1530 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1532 // We express dash pattern in pen width unit, so we are
1533 // independent of zoom factor and so on...
1535 const wxX11Dash
*req_dash
;
1537 switch (m_pen
.GetStyle ())
1540 req_nb_dash
= m_currentPenDashCount
;
1541 req_dash
= m_currentPenDash
;
1542 style
= LineOnOffDash
;
1547 style
= LineOnOffDash
;
1551 req_dash
= short_dashed
;
1552 style
= LineOnOffDash
;
1556 req_dash
= long_dashed
;
1557 style
= LineOnOffDash
;
1561 req_dash
= dotted_dashed
;
1562 style
= LineOnOffDash
;
1569 req_dash
= (wxX11Dash
*)NULL
;
1573 if (req_dash
&& req_nb_dash
)
1575 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1578 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1579 for (int i
= 0; i
< req_nb_dash
; i
++)
1580 real_req_dash
[i
] = (wxX11Dash
)(req_dash
[i
] * factor
);
1581 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1583 if (m_window
&& m_window
->GetBackingPixmap())
1584 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1585 delete[]real_req_dash
;
1589 // No Memory. We use non-scaled dash pattern...
1590 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1592 if (m_window
&& m_window
->GetBackingPixmap())
1593 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1597 switch (m_pen
.GetCap ())
1599 case wxCAP_PROJECTING
:
1600 cap
= CapProjecting
;
1607 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1611 switch (m_pen
.GetJoin ())
1625 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1627 if (m_window
&& m_window
->GetBackingPixmap())
1628 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1631 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1635 oldStipple
= wxNullBitmap
; // For later reset!!
1637 switch (m_currentFill
)
1639 case wxBDIAGONAL_HATCH
:
1640 if (bdiag
== (Pixmap
) 0)
1641 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1642 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1643 bdiag_bits
, bdiag_width
, bdiag_height
);
1646 case wxFDIAGONAL_HATCH
:
1647 if (fdiag
== (Pixmap
) 0)
1648 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1649 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1650 fdiag_bits
, fdiag_width
, fdiag_height
);
1654 if (cross
== (Pixmap
) 0)
1655 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1656 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1657 cross_bits
, cross_width
, cross_height
);
1660 case wxHORIZONTAL_HATCH
:
1661 if (horiz
== (Pixmap
) 0)
1662 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1663 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1664 horiz_bits
, horiz_width
, horiz_height
);
1667 case wxVERTICAL_HATCH
:
1668 if (verti
== (Pixmap
) 0)
1669 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1670 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1671 verti_bits
, verti_width
, verti_height
);
1674 case wxCROSSDIAG_HATCH
:
1676 if (cdiag
== (Pixmap
) 0)
1677 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1678 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1679 cdiag_bits
, cdiag_width
, cdiag_height
);
1683 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1685 if (m_window
&& m_window
->GetBackingPixmap())
1686 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1688 else if (m_currentStipple
.Ok()
1689 && ((!m_currentStipple
.IsSameAs(oldStipple
)) || !GET_OPTIMIZATION
))
1691 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetDrawable());
1693 if (m_window
&& m_window
->GetBackingPixmap())
1694 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetDrawable());
1697 if ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
)
1701 if (m_currentFill
== wxSTIPPLE
)
1702 fill_style
= FillStippled
;
1703 else if (IS_HATCH (m_currentFill
))
1704 fill_style
= FillStippled
;
1706 fill_style
= FillSolid
;
1707 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1708 if (m_window
&& m_window
->GetBackingPixmap())
1709 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1712 // must test m_logicalFunction, because it involves background!
1713 if (!sameColour
|| !GET_OPTIMIZATION
1714 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1717 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1718 pixel
= m_backgroundPixel
;
1721 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, false);
1724 // Finally, set the GC to the required colour
1726 SetForegroundPixelWithLogicalFunction(pixel
);
1729 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1734 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1736 wxCHECK_RET( Ok(), "invalid dc" );
1740 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1743 int oldFill
= m_currentFill
;
1744 wxBitmap oldStipple
= m_currentStipple
;
1746 m_autoSetting
|= 0x1;
1748 m_currentFill
= m_brush
.GetStyle ();
1749 if (m_currentFill
== wxSTIPPLE
)
1750 m_currentStipple
= * m_brush
.GetStipple ();
1752 wxColour
oldBrushColour(m_currentColour
);
1753 m_currentColour
= m_brush
.GetColour ();
1755 bool sameColour
= (oldBrushColour
.Ok () &&
1756 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1757 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1758 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1759 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1761 int stippleDepth
= -1;
1763 if ((oldFill
!= m_brush
.GetStyle ()) || !GET_OPTIMIZATION
)
1765 switch (brush
.GetStyle ())
1770 stippleDepth
= m_currentStipple
.GetDepth();
1772 case wxBDIAGONAL_HATCH
:
1773 case wxCROSSDIAG_HATCH
:
1774 case wxFDIAGONAL_HATCH
:
1776 case wxHORIZONTAL_HATCH
:
1777 case wxVERTICAL_HATCH
:
1779 if (stippleDepth
== -1) stippleDepth
= 1;
1781 // Chris Breeze 23/07/97: use background mode to
1782 // determine whether fill style should be solid or
1784 int style
= stippleDepth
== 1 ?
1785 (m_backgroundMode
== wxSOLID
?
1786 FillOpaqueStippled
: FillStippled
) :
1788 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1789 if (m_window
&& m_window
->GetBackingPixmap())
1790 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1795 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1796 if (m_window
&& m_window
->GetBackingPixmap())
1797 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
,
1802 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GET_OPTIMIZATION
))
1806 switch (m_currentFill
)
1808 case wxBDIAGONAL_HATCH
:
1809 if (bdiag
== (Pixmap
) 0)
1810 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1811 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1812 bdiag_bits
, bdiag_width
, bdiag_height
);
1815 case wxFDIAGONAL_HATCH
:
1816 if (fdiag
== (Pixmap
) 0)
1817 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1818 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1819 fdiag_bits
, fdiag_width
, fdiag_height
);
1823 if (cross
== (Pixmap
) 0)
1824 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1825 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1826 cross_bits
, cross_width
, cross_height
);
1829 case wxHORIZONTAL_HATCH
:
1830 if (horiz
== (Pixmap
) 0)
1831 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1832 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1833 horiz_bits
, horiz_width
, horiz_height
);
1836 case wxVERTICAL_HATCH
:
1837 if (verti
== (Pixmap
) 0)
1838 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1839 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1840 verti_bits
, verti_width
, verti_height
);
1843 case wxCROSSDIAG_HATCH
:
1845 if (cdiag
== (Pixmap
) 0)
1846 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1847 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1848 cdiag_bits
, cdiag_width
, cdiag_height
);
1852 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1854 if (m_window
&& m_window
->GetBackingPixmap())
1855 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1857 // X can forget the stipple value when resizing a window (apparently)
1858 // so always set the stipple.
1859 else if (m_currentFill
!= wxSOLID
&& m_currentFill
!= wxTRANSPARENT
&&
1860 m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1862 if (m_currentStipple
.GetDepth() == 1)
1864 XSetStipple ((Display
*) m_display
, (GC
) m_gc
,
1865 (Pixmap
) m_currentStipple
.GetDrawable());
1866 if (m_window
&& m_window
->GetBackingPixmap())
1867 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
,
1868 (Pixmap
) m_currentStipple
.GetDrawable());
1872 XSetTile ((Display
*) m_display
, (GC
) m_gc
,
1873 (Pixmap
) m_currentStipple
.GetDrawable());
1874 if (m_window
&& m_window
->GetBackingPixmap())
1875 XSetTile ((Display
*) m_display
,(GC
) m_gcBacking
,
1876 (Pixmap
) m_currentStipple
.GetDrawable());
1880 // must test m_logicalFunction, because it involves background!
1881 if (!sameColour
|| !GET_OPTIMIZATION
|| m_logicalFunction
== wxXOR
)
1883 WXPixel pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, true);
1886 SetForegroundPixelWithLogicalFunction(pixel
);
1889 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1892 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1894 wxCHECK_RET( Ok(), "invalid dc" );
1896 m_backgroundBrush
= brush
;
1898 if (!m_backgroundBrush
.Ok())
1901 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1903 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1904 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1905 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
1906 if (m_window
&& m_window
->GetBackingPixmap())
1907 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1911 void wxWindowDC::SetLogicalFunction( int function
)
1913 wxCHECK_RET( Ok(), "invalid dc" );
1918 if (m_logicalFunction
== function
)
1924 x_function
= GXclear
;
1930 x_function
= GXinvert
;
1933 x_function
= GXorReverse
;
1936 x_function
= GXandReverse
;
1945 x_function
= GXandInverted
;
1948 x_function
= GXnoop
;
1954 x_function
= GXequiv
;
1957 x_function
= GXcopyInverted
;
1960 x_function
= GXorInverted
;
1963 x_function
= GXnand
;
1970 x_function
= GXcopy
;
1974 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1975 if (m_window
&& m_window
->GetBackingPixmap())
1976 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
1978 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1979 /* MATTHEW: [9] Need to redo pen simply */
1980 m_autoSetting
|= 0x2;
1982 m_logicalFunction
= function
;
1986 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1988 wxCHECK_RET( Ok(), "invalid dc" );
1990 m_textForegroundColour
= col
;
1993 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1995 wxCHECK_RET( Ok(), "invalid dc" );
1997 m_textBackgroundColour
= col
;
2000 void wxWindowDC::SetBackgroundMode( int mode
)
2002 m_backgroundMode
= mode
;
2005 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2010 /* Use GetXColormap */
2011 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2012 (Colormap
) palette
.GetXColormap());
2014 /* Use wxGetMainColormap */
2015 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2016 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2020 static void wxCopyRegion( WXRegion src
, WXRegion
& dst
)
2023 dst
= XCreateRegion();
2024 XUnionRegion( (Region
)src
, (Region
)src
, (Region
)dst
);
2027 // Helper function; userRegion is the region set by calling SetClippingRegion
2028 void wxWindowDC::SetDCClipping( WXRegion userRegion
)
2030 bool hasUpdateRegion
= m_window
&& m_window
->GetUpdateRegion().Ok();
2031 // this means that we should start the clip region from scratch,
2032 // or from the update region, if any
2036 XDestroyRegion( (Region
)m_clipRegion
);
2037 m_clipRegion
= (WXRegion
)NULL
;
2039 if( hasUpdateRegion
)
2040 wxCopyRegion( m_window
->GetUpdateRegion().GetX11Region(),
2043 // intersect the user region, if any, with the
2044 // exisiting clip region
2045 else // if( userRegion )
2048 wxCopyRegion( userRegion
, m_clipRegion
);
2050 XIntersectRegion( (Region
)m_clipRegion
,
2051 (Region
)userRegion
, (Region
)m_clipRegion
);
2055 XSetRegion( (Display
*)m_display
, (GC
)m_gc
, (Region
)m_clipRegion
);
2057 XSetClipMask( (Display
*)m_display
, (GC
)m_gc
, None
);
2060 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
,
2061 wxCoord width
, wxCoord height
)
2063 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2065 wxRegion
temp(XLOG2DEV(x
), YLOG2DEV(y
),
2066 XLOG2DEVREL(width
), YLOG2DEVREL(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
= (short)XLOG2DEV_2(x
);
2076 rects
[0].y
= (short)YLOG2DEV_2(y
);
2077 rects
[0].width
= (unsigned short)XLOG2DEVREL(width
);
2078 rects
[0].height
= (unsigned short)YLOG2DEVREL(height
);
2079 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2080 0, 0, rects
, 1, Unsorted
);
2084 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2086 SetDCClipping(region
.GetX11Region());
2088 // Needs to work differently for Pixmap: without this,
2089 // there's a nasty (Display*) m_display bug. 8/12/94
2090 if (m_window
&& m_window
->GetBackingPixmap())
2092 wxRect box
= region
.GetBox();
2094 XRectangle rects
[1];
2095 rects
[0].x
= (short)XLOG2DEV_2(box
.x
);
2096 rects
[0].y
= (short)YLOG2DEV_2(box
.y
);
2097 rects
[0].width
= (unsigned short)XLOG2DEVREL(box
.width
);
2098 rects
[0].height
= (unsigned short)YLOG2DEVREL(box
.height
);
2099 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
,
2100 0, 0, rects
, 1, Unsorted
);
2105 void wxWindowDC::DestroyClippingRegion()
2107 wxDC::DestroyClippingRegion();
2109 SetDCClipping(NULL
);
2111 if (m_window
&& m_window
->GetBackingPixmap())
2112 XSetClipMask ((Display
*) m_display
, (GC
) m_gcBacking
, None
);
2115 // Resolution in pixels per logical inch
2116 wxSize
wxWindowDC::GetPPI() const
2119 return wxSize(100, 100);
2122 int wxWindowDC::GetDepth() const
2131 // ----------------------------------------------------------------------------
2133 // ----------------------------------------------------------------------------
2135 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2137 // Set the clipping region.to the update region
2138 SetDCClipping((WXRegion
)NULL
);
2141 wxPaintDC::~wxPaintDC()
2144 m_window
->ClearUpdateRegion();
2145 SetDCClipping((WXRegion
)NULL
);
2148 // ----------------------------------------------------------------------------
2149 // private functions
2150 // ----------------------------------------------------------------------------
2153 Used when copying between drawables on different (Display*) m_displays. Not
2154 very fast, but better than giving up.
2157 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2158 Drawable src
, Drawable dest
,
2161 unsigned int w
, unsigned int h
,
2162 int destx
, int desty
,
2163 bool more
, XImage
**cache
)
2165 XImage
*image
, *destimage
;
2166 Colormap destcm
, srccm
;
2167 static const int CACHE_SIZE
= 256;
2170 Pixel cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2171 int k
, cache_pos
, all_cache
;
2173 if (!cache
|| !*cache
)
2174 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2178 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2180 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2181 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2186 for (i
= 0; i
< w
; i
++)
2187 for (j
= 0; j
< h
; j
++) {
2191 pixel
= XGetPixel(image
, i
, j
);
2192 for (k
= cache_pos
; k
--; )
2193 if (cachesrc
[k
] == pixel
) {
2194 pixel
= cachedest
[k
];
2198 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2199 if (cachesrc
[k
] == pixel
) {
2200 pixel
= cachedest
[k
];
2204 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2205 XQueryColor(src_display
, srccm
, &xcol
);
2206 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2208 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2210 if (++cache_pos
>= CACHE_SIZE
) {
2216 XPutPixel(destimage
, i
, j
, pixel
);
2219 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2220 XDestroyImage(destimage
);
2225 XDestroyImage(image
);
2230 /* Helper function for 16-bit fonts */
2231 static int str16len(const char *s
)
2235 while (s
[0] && s
[1]) {