1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 About pens, brushes, and the autoSetting flag:
15 Under X, pens and brushes control some of the same X drawing parameters.
16 Therefore, it is impossible to independently maintain the current pen and the
17 current brush. Also, some settings depend on the current logical function. The
18 m_currentFill, etc. instance variables remember state across the brush and
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
31 // ============================================================================
33 // ============================================================================
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
40 #pragma implementation "dcclient.h"
43 #include "wx/dcclient.h"
44 #include "wx/dcmemory.h"
45 #include "wx/window.h"
52 #pragma message disable nosimpint
55 #pragma message enable nosimpint
58 #include "wx/x11/private.h"
61 #include <float.h> // for M_PI
71 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 // Fudge factor (VZ: what??)
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
84 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
85 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
86 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
88 // ----------------------------------------------------------------------------
90 // ----------------------------------------------------------------------------
92 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
93 Drawable src
, Drawable dest
,
96 unsigned int w
, unsigned int h
,
98 bool more
, XImage
**cache
);
100 // ============================================================================
102 // ============================================================================
105 * compare two doubles and return the larger rounded
108 static int roundmax(double a
, double b
)
110 return (int)((a
> b
? a
: b
) + 0.5);
114 * compare two doubles and return the smaller rounded
117 static int roundmin(double a
, double b
)
119 return (int)((a
< b
? a
: b
) - 0.5);
123 // ----------------------------------------------------------------------------
125 // ----------------------------------------------------------------------------
127 wxWindowDC::wxWindowDC()
130 m_gcBacking
= (WXGC
) 0;
132 m_backgroundPixel
= -1;
133 m_currentPenWidth
= 1;
134 m_currentPenJoin
= -1;
135 m_currentPenDashCount
= -1;
136 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
139 // m_currentBkMode = wxTRANSPARENT;
140 m_colour
= wxColourDisplay();
141 m_display
= (WXDisplay
*) NULL
;
142 m_currentRegion
= (WXRegion
) 0;
143 m_userRegion
= (WXRegion
) 0;
144 m_pixmap
= (WXPixmap
) 0;
146 m_oldFont
= (WXFont
) 0;
149 wxWindowDC::wxWindowDC( wxWindow
*window
)
151 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
154 m_font
= window
->GetFont();
156 m_gcBacking
= (WXGC
) 0;
157 m_backgroundPixel
= -1;
158 m_currentPenWidth
= 1;
159 m_currentPenJoin
= -1;
160 m_currentPenDashCount
= -1;
161 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
164 // m_currentBkMode = wxTRANSPARENT;
165 m_colour
= wxColourDisplay();
166 m_currentRegion
= (WXRegion
) 0;
167 m_userRegion
= (WXRegion
) 0;
171 m_display
= window
->GetXDisplay();
172 m_pixmap
= window
->GetXWindow();
173 Display
* display
= (Display
*) m_display
;
175 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
178 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
179 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
180 gcvalues
.graphics_exposures
= False
;
181 gcvalues
.subwindow_mode
= IncludeInferiors
;
182 gcvalues
.line_width
= 1;
183 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
184 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
187 if (m_window
->GetBackingPixmap())
189 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
190 DefaultScreen (display
)),
191 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
195 m_backgroundPixel
= (int) gcvalues
.background
;
197 // Get the current Font so we can set it back later
199 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
200 m_oldFont
= (WXFont
) valReturn
.font
;
202 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
205 wxWindowDC::~wxWindowDC()
207 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
209 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
211 if (m_window
&& m_window
->GetBackingPixmap())
212 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
216 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
220 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
221 m_gcBacking
= (WXGC
) 0;
224 XDestroyRegion ((Region
) m_currentRegion
);
225 m_currentRegion
= (WXRegion
) 0;
228 XDestroyRegion ((Region
) m_userRegion
);
229 m_userRegion
= (WXRegion
) 0;
232 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
233 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
235 wxFAIL_MSG("not implemented");
238 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
240 // Generic (and therefore rather inefficient) method.
241 // Could be improved.
243 wxBitmap
bitmap(1, 1);
244 memdc
.SelectObject(bitmap
);
245 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
246 memdc
.SelectObject(wxNullBitmap
);
247 wxImage
image(bitmap
);
248 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
252 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
254 wxCHECK_RET( Ok(), "invalid dc" );
256 int x1d
, y1d
, x2d
, y2d
;
258 // FreeGetPixelCache();
268 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
270 if (m_window
&& m_window
->GetBackingPixmap())
271 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
272 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
273 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
275 CalcBoundingBox(x1
, y1
);
276 CalcBoundingBox(x2
, y2
);
279 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
281 wxCHECK_RET( Ok(), "invalid dc" );
286 int xx
= XLOG2DEV (x
);
287 int yy
= YLOG2DEV (y
);
289 wxDisplaySize (&ww
, &hh
);
290 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
292 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
295 if (m_window
&& m_window
->GetBackingPixmap())
299 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
302 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
308 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
310 wxCHECK_RET( Ok(), "invalid dc" );
312 // FreeGetPixelCache();
314 int xx1
= XLOG2DEV (x1
);
315 int yy1
= YLOG2DEV (y1
);
316 int xx2
= XLOG2DEV (x2
);
317 int yy2
= YLOG2DEV (y2
);
318 int xxc
= XLOG2DEV (xc
);
319 int yyc
= YLOG2DEV (yc
);
320 int xxc_2
= XLOG2DEV_2 (xc
);
321 int yyc_2
= YLOG2DEV_2 (yc
);
323 wxCoord dx
= xx1
- xxc
;
324 wxCoord dy
= yy1
- yyc
;
325 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
326 wxCoord r
= (wxCoord
) radius
;
328 double radius1
, radius2
;
330 if (xx1
== xx2
&& yy1
== yy2
)
335 else if (radius
== 0.0)
336 radius1
= radius2
= 0.0;
345 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
353 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
357 int alpha1
= (int) radius1
;
358 int alpha2
= (int) (radius2
- radius1
);
361 while (alpha2
> 360 * 64)
364 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
367 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
368 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
370 if (m_window
&& m_window
->GetBackingPixmap())
371 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
372 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
376 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
380 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
381 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
383 if (m_window
&& m_window
->GetBackingPixmap())
384 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
385 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
387 CalcBoundingBox (x1
, y1
);
388 CalcBoundingBox (x2
, y2
);
391 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
393 wxCHECK_RET( Ok(), "invalid dc" );
399 wd
= XLOG2DEVREL(width
);
400 hd
= YLOG2DEVREL(height
);
402 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
403 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
404 int start
= int(sa
*64);
405 int end
= int(ea
*64);
406 if (start
<0) start
+=360*64;
407 if (end
<0) end
+=360*64;
408 if (end
>start
) end
-=start
;
409 else end
+=360*64-start
;
411 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
413 m_autoSetting
= TRUE
; // must be reset
416 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
418 if (m_window
&& m_window
->GetBackingPixmap())
419 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
420 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
423 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
427 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
428 if (m_window
&& m_window
->GetBackingPixmap())
429 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
430 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
432 CalcBoundingBox (x
, y
);
433 CalcBoundingBox (x
+ width
, y
+ height
);
436 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
438 wxCHECK_RET( Ok(), "invalid dc" );
440 // FreeGetPixelCache();
442 if (m_pen
.Ok() && m_autoSetting
)
445 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
446 if (m_window
&& m_window
->GetBackingPixmap())
447 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
449 CalcBoundingBox (x
, y
);
452 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
454 wxCHECK_RET( Ok(), "invalid dc" );
456 // FreeGetPixelCache();
458 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
463 XPoint
*xpoints
= new XPoint
[n
];
466 for (i
= 0; i
< n
; i
++)
468 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
469 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
471 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
473 if (m_window
&& m_window
->GetBackingPixmap())
475 for (i
= 0; i
< n
; i
++)
477 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
478 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
480 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
486 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
487 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
489 wxCHECK_RET( Ok(), "invalid dc" );
491 // FreeGetPixelCache();
493 XPoint
*xpoints1
= new XPoint
[n
+ 1];
494 XPoint
*xpoints2
= new XPoint
[n
+ 1];
496 for (i
= 0; i
< n
; i
++)
498 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
499 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
500 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
501 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
502 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
505 // Close figure for XDrawLines (not needed for XFillPolygon)
506 xpoints1
[i
].x
= xpoints1
[0].x
;
507 xpoints1
[i
].y
= xpoints1
[0].y
;
508 xpoints2
[i
].x
= xpoints2
[0].x
;
509 xpoints2
[i
].y
= xpoints2
[0].y
;
511 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
514 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
515 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
516 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
517 if (m_window
&& m_window
->GetBackingPixmap())
519 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
520 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
521 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
522 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
526 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
530 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
532 if (m_window
&& m_window
->GetBackingPixmap())
533 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
540 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
542 wxCHECK_RET( Ok(), "invalid dc" );
544 // FreeGetPixelCache();
546 int xd
, yd
, wfd
, hfd
, wd
, hd
;
550 wfd
= XLOG2DEVREL(width
);
552 hfd
= YLOG2DEVREL(height
);
555 if (wfd
== 0 || hfd
== 0) return;
556 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
557 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
559 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
562 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
564 if (m_window
&& m_window
->GetBackingPixmap())
565 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
566 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
570 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
574 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
576 if (m_window
&& m_window
->GetBackingPixmap())
577 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
578 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
581 CalcBoundingBox (x
, y
);
582 CalcBoundingBox (x
+ width
, y
+ height
);
585 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
587 wxCHECK_RET( Ok(), "invalid dc" );
589 // FreeGetPixelCache();
591 // If radius is negative, it's a proportion of the smaller dimension.
593 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
595 int xd
= XLOG2DEV (x
);
596 int yd
= YLOG2DEV (y
);
597 int rd
= XLOG2DEVREL ((long) radius
);
598 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
599 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
604 // If radius is zero use DrawRectangle() instead to avoid
605 // X drawing errors with small radii
608 DrawRectangle( x
, y
, width
, height
);
612 // Draw nothing if transformed w or h is 0
613 if (wd
== 0 || hd
== 0) return;
615 // CMB: adjust size if outline is drawn otherwise the result is
616 // 1 pixel too wide and high
617 if (m_pen
.GetStyle() != wxTRANSPARENT
)
623 // CMB: ensure dd is not larger than rectangle otherwise we
624 // get an hour glass shape
625 if (rw_d
> wd
) rw_d
= wd
;
626 if (rw_d
> hd
) rw_d
= hd
;
629 // For backing pixmap
630 int xd2
= XLOG2DEV_2 (x
);
631 int yd2
= YLOG2DEV_2 (y
);
632 int rd2
= XLOG2DEVREL ((long) radius
);
633 int wd2
= XLOG2DEVREL (width
) ;
634 int hd2
= YLOG2DEVREL (height
) ;
639 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
643 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
645 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
648 // Arcs start from 3 o'clock, positive angles anticlockwise
650 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
651 rw_d
, rh_d
, 90 * 64, 90 * 64);
653 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
654 // rw_d, rh_d, 0, 90 * 64);
655 rw_d
, rh_d
, 0, 91 * 64);
657 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
659 // rw_d, rh_d, 270 * 64, 90 * 64);
660 rw_d
, rh_d
, 269 * 64, 92 * 64);
662 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
663 rw_d
, rh_d
, 180 * 64, 90 * 64);
665 if (m_window
&& m_window
->GetBackingPixmap())
667 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
668 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
669 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
670 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
672 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
673 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
674 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
675 xd2
+ wd2
- rw_d2
, yd2
,
676 // rw_d2, rh_d2, 0, 90 * 64);
677 rw_d2
, rh_d2
, 0, 91 * 64);
678 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
681 // rw_d2, rh_d2, 270 * 64, 90 * 64);
682 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
683 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
684 xd2
, yd2
+ hd2
- rh_d2
,
685 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
689 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
693 xd
+ wd
- rd
+ 1, yd
);
694 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
695 xd
+ wd
- rd
, yd
+ hd
);
697 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
699 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
700 xd
+ wd
, yd
+ hd
- rd
+ 1);
701 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
702 rw_d
, rh_d
, 90 * 64, 90 * 64);
703 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
704 // rw_d, rh_d, 0, 90 * 64);
705 rw_d
, rh_d
, 0, 91 * 64);
706 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
708 rw_d
, rh_d
, 269 * 64, 92 * 64);
709 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
710 rw_d
, rh_d
, 180 * 64, 90 * 64);
712 if (m_window
&& m_window
->GetBackingPixmap())
714 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
716 xd2
+ wd2
- rd2
+ 1, yd2
);
717 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
718 xd2
+ rd2
, yd2
+ hd2
,
719 xd2
+ wd2
- rd2
, yd2
+ hd2
);
721 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
723 xd2
, yd2
+ hd2
- rd2
);
724 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
725 xd2
+ wd2
, yd2
+ rd2
,
726 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
727 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
729 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
730 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
731 xd2
+ wd2
- rw_d2
, yd2
,
732 // rw_d2, rh_d2, 0, 90 * 64);
733 rw_d2
, rh_d2
, 0, 91 * 64);
734 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
737 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
738 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
739 xd2
, yd2
+ hd2
- rh_d2
,
740 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
743 CalcBoundingBox (x
, y
);
744 CalcBoundingBox (x
+ width
, y
+ height
);
749 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
751 wxCHECK_RET( Ok(), "invalid dc" );
753 // Check for negative width and height
766 // FreeGetPixelCache();
768 static const int angle
= 23040;
774 wd
= XLOG2DEVREL(width
) ;
775 hd
= YLOG2DEVREL(height
) ;
777 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
780 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
781 if (m_window
&& m_window
->GetBackingPixmap())
782 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
783 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
784 XLOG2DEVREL (width
) - WX_GC_CF
,
785 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
788 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
792 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
793 if (m_window
&& m_window
->GetBackingPixmap())
794 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
795 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
796 XLOG2DEVREL (width
) - WX_GC_CF
,
797 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
799 CalcBoundingBox (x
, y
);
800 CalcBoundingBox (x
+ width
, y
+ height
);
804 bool wxWindowDC::CanDrawBitmap() const
806 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
812 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
814 // FreeGetPixelCache();
816 // Be sure that foreground pixels (1) of
817 // the Icon will be painted with pen colour. [m_pen.SetColour()]
818 // Background pixels (0) will be painted with
819 // last selected background color. [::SetBackground]
820 if (m_pen
.Ok() && m_autoSetting
)
824 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
825 width
= icon
.GetWidth();
826 height
= icon
.GetHeight();
827 if (icon
.GetDisplay() == m_display
)
829 if (icon
.GetDepth() <= 1)
831 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
833 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
837 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
839 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
843 if (m_window
&& m_window
->GetBackingPixmap())
845 if (icon
.GetDepth() <= 1)
847 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
848 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
852 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
854 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
857 } else { /* Remote copy (different (Display*) m_displays) */
858 XImage
*cache
= NULL
;
859 if (m_window
&& m_window
->GetBackingPixmap())
860 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
861 (GC
) m_gcBacking
, 0, 0, width
, height
,
862 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
863 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
865 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
867 CalcBoundingBox (x
, y
);
871 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
872 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
873 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
874 wxCoord xsrcMask
, wxCoord ysrcMask
)
876 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
878 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
880 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
882 // FreeGetPixelCache();
884 // Be sure that foreground pixels (1) of the Icon will be painted with pen
885 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
886 // last selected background color. [::SetBackground]
887 if (m_pen
.Ok() && m_autoSetting
)
890 // Do bitmap scaling if necessary
892 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
893 Pixmap sourcePixmap
= (Pixmap
) NULL
;
894 double scaleX
, scaleY
;
895 GetUserScale(& scaleX
, & scaleY
);
897 /* TODO: use the mask origin when drawing transparently */
898 if (xsrcMask
== -1 && ysrcMask
== -1)
900 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
903 // Sorry, can't scale masks just yet
904 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
906 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
907 wxBitmap
& bitmap
= memDC
->GetBitmap();
909 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
911 wxImage
image(bitmap
);
914 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
918 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
919 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
921 image
= image
.Scale(scaledW
, scaledH
);
922 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
923 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
927 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
929 if (m_pixmap
&& sourcePixmap
)
932 int orig
= m_logicalFunction
;
934 SetLogicalFunction (rop
);
936 if (m_display
!= sourceDC
->m_display
)
938 XImage
*cache
= NULL
;
940 if (m_window
&& m_window
->GetBackingPixmap())
941 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
942 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
944 source
->LogicalToDeviceX (xsrc
),
945 source
->LogicalToDeviceY (ysrc
),
946 source
->LogicalToDeviceXRel(width
),
947 source
->LogicalToDeviceYRel(height
),
948 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
951 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
953 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
954 wxBitmap
& sel
= memDC
->GetBitmap();
955 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
957 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
958 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
962 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
963 source
->LogicalToDeviceX (xsrc
),
964 source
->LogicalToDeviceY (ysrc
),
965 source
->LogicalToDeviceXRel(width
),
966 source
->LogicalToDeviceYRel(height
),
967 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
972 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
973 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
978 if (m_window
&& m_window
->GetBackingPixmap())
980 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
981 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
983 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
984 source
->LogicalToDeviceX (xsrc
),
985 source
->LogicalToDeviceY (ysrc
),
986 source
->LogicalToDeviceXRel(width
),
987 source
->LogicalToDeviceYRel(height
),
988 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
992 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
993 source
->LogicalToDeviceX (xsrc
),
994 source
->LogicalToDeviceY (ysrc
),
995 source
->LogicalToDeviceXRel(width
),
996 source
->LogicalToDeviceYRel(height
),
997 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
1000 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1002 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1003 wxBitmap
& sel
= memDC
->GetBitmap();
1004 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1006 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1007 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1011 // Check if we're copying from a mono bitmap
1012 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1013 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1015 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1016 source
->LogicalToDeviceX (xsrc
),
1017 source
->LogicalToDeviceY (ysrc
),
1018 source
->LogicalToDeviceXRel(width
),
1019 source
->LogicalToDeviceYRel(height
),
1020 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1024 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1025 source
->LogicalToDeviceX (xsrc
),
1026 source
->LogicalToDeviceY (ysrc
),
1027 source
->LogicalToDeviceXRel(width
),
1028 source
->LogicalToDeviceYRel(height
),
1029 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1034 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1035 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1038 } /* Remote/local (Display*) m_display */
1039 CalcBoundingBox (xdest
, ydest
);
1040 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1042 SetLogicalFunction(orig
);
1044 if (scaledBitmap
) delete scaledBitmap
;
1048 if (scaledBitmap
) delete scaledBitmap
;
1053 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1055 wxCHECK_RET( Ok(), "invalid dc" );
1057 // Since X draws from the baseline of the text, must add the text height
1063 slen
= strlen(text
);
1067 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1068 int direction
, descent
;
1069 XCharStruct overall_return
;
1072 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1073 &ascent
, &descent
, &overall_return
);
1076 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1077 &ascent
, &descent
, &overall_return
);
1079 cx
= overall_return
.width
;
1080 cy
= ascent
+ descent
;
1083 // First draw a rectangle representing the text background, if a text
1084 // background is specified
1085 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1087 wxColour oldPenColour
= m_currentColour
;
1088 m_currentColour
= m_textBackgroundColour
;
1089 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1090 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1091 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1092 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1094 // This separation of the big && test required for gcc2.7/HP UX 9.02
1095 // or pixel value can be corrupted!
1096 sameColour
= (sameColour
&&
1097 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1099 if (!sameColour
|| !GetOptimization())
1101 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1102 m_currentColour
= m_textBackgroundColour
;
1104 // Set the GC to the required colour
1107 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1108 if (m_window
&& m_window
->GetBackingPixmap())
1109 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1113 m_textBackgroundColour
= oldPenColour
;
1115 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1116 if (m_window
&& m_window
->GetBackingPixmap())
1117 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1118 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1121 // Now set the text foreground and draw the text
1122 if (m_textForegroundColour
.Ok ())
1124 wxColour oldPenColour
= m_currentColour
;
1125 m_currentColour
= m_textForegroundColour
;
1126 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1127 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1128 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1129 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1130 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1132 if (!sameColour
|| !GetOptimization())
1135 if (!m_colour
) // Mono display
1137 // Unless foreground is really white, draw it in black
1138 unsigned char red
= m_textForegroundColour
.Red ();
1139 unsigned char blue
= m_textForegroundColour
.Blue ();
1140 unsigned char green
= m_textForegroundColour
.Green ();
1141 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1142 && green
== (unsigned char) 255)
1144 m_currentColour
= *wxWHITE
;
1145 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1146 m_currentColour
.SetPixel(pixel
);
1147 m_textForegroundColour
.SetPixel(pixel
);
1151 m_currentColour
= *wxBLACK
;
1152 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1153 m_currentColour
.SetPixel(pixel
);
1154 m_textForegroundColour
.SetPixel(pixel
);
1159 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1160 m_currentColour
.SetPixel(pixel
);
1163 // Set the GC to the required colour
1166 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1167 if (m_window
&& m_window
->GetBackingPixmap())
1168 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1172 m_textForegroundColour
= oldPenColour
;
1175 // We need to add the ascent, not the whole height, since X draws at the
1176 // point above the descender.
1179 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1180 (XChar2b
*)(char*) (const char*) text
, slen
);
1183 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1185 if (m_window
&& m_window
->GetBackingPixmap()) {
1188 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1189 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1190 (XChar2b
*)(char*) (const char*) text
, slen
);
1193 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1194 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1198 GetTextExtent (text
, &w
, &h
);
1199 CalcBoundingBox (x
+ w
, y
+ h
);
1200 CalcBoundingBox (x
, y
);
1203 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1207 DrawText(text
, x
, y
);
1211 wxCHECK_RET( Ok(), "invalid dc" );
1213 // Since X draws from the baseline of the text, must add the text height
1219 slen
= strlen(text
);
1223 // Calculate text extent.
1224 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1225 int direction
, descent
;
1226 XCharStruct overall_return
;
1229 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1230 &ascent
, &descent
, &overall_return
);
1233 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1234 &ascent
, &descent
, &overall_return
);
1236 cx
= overall_return
.width
;
1237 cy
= ascent
+ descent
;
1240 wxBitmap
src(cx
, cy
);
1242 dc
.SelectObject(src
);
1243 dc
.SetFont(GetFont());
1244 dc
.SetBackground(*wxWHITE_BRUSH
);
1245 dc
.SetBrush(*wxBLACK_BRUSH
);
1247 dc
.DrawText(text
, 0, 0);
1248 dc
.SetFont(wxNullFont
);
1250 // Calculate the size of the rotated bounding box.
1251 double dx
= cos(angle
/ 180.0 * M_PI
);
1252 double dy
= sin(angle
/ 180.0 * M_PI
);
1253 double x4
= -cy
* dy
;
1254 double y4
= cy
* dx
;
1255 double x3
= cx
* dx
;
1256 double y3
= cx
* dy
;
1257 double x2
= x3
+ x4
;
1258 double y2
= y3
+ y4
;
1262 // Create image from the source bitmap after writing the text into it.
1265 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1266 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1267 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1268 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1270 // This rotates counterclockwise around the top left corner.
1271 for (int rx
= minx
; rx
< maxx
; rx
++)
1273 for (int ry
= miny
; ry
< maxy
; ry
++)
1275 // transform dest coords to source coords
1276 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1277 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1278 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1280 // draw black pixels, ignore white ones (i.e. transparent b/g)
1281 if (image
.GetRed(sx
, sy
) == 0)
1283 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1288 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1295 // First draw a rectangle representing the text background, if a text
1296 // background is specified
1297 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1299 wxColour oldPenColour
= m_currentColour
;
1300 m_currentColour
= m_textBackgroundColour
;
1301 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1302 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1303 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1304 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1306 // This separation of the big && test required for gcc2.7/HP UX 9.02
1307 // or pixel value can be corrupted!
1308 sameColour
= (sameColour
&&
1309 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1311 if (!sameColour
|| !GetOptimization())
1313 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1314 m_currentColour
= m_textBackgroundColour
;
1316 // Set the GC to the required colour
1319 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1320 if (m_window
&& m_window
->GetBackingPixmap())
1321 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1325 m_textBackgroundColour
= oldPenColour
;
1327 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1328 if (m_window
&& m_window
->GetBackingPixmap())
1329 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1330 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1335 // XXX use pixmap size
1336 GetTextExtent (text
, &w
, &h
);
1337 CalcBoundingBox (x
+ w
, y
+ h
);
1338 CalcBoundingBox (x
, y
);
1341 bool wxWindowDC::CanGetTextExtent() const
1346 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1347 wxCoord
*descent
, wxCoord
*externalLeading
,
1348 wxFont
*font
) const
1350 wxCHECK_RET( Ok(), "invalid dc" );
1352 wxFont
* theFont
= font
;
1354 theFont
= (wxFont
*)&m_font
; // const_cast
1358 // TODO: this should be an error log function
1359 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1361 if (width
) *width
= -1;
1362 if (height
) *height
= -1;
1366 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1368 int direction
, ascent
, descent2
;
1369 XCharStruct overall
;
1374 slen
= str16len(string
);
1377 slen
= strlen(string
);
1381 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1382 &ascent
, &descent2
, &overall
);
1385 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1386 &ascent
, &descent2
, &overall
);
1388 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1389 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1391 *descent
= descent2
;
1392 if (externalLeading
)
1393 *externalLeading
= 0;
1396 wxCoord
wxWindowDC::GetCharWidth() const
1398 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1399 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1401 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1403 int direction
, ascent
, descent
;
1404 XCharStruct overall
;
1405 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1406 &descent
, &overall
);
1407 return XDEV2LOGREL(overall
.width
);
1410 wxCoord
wxWindowDC::GetCharHeight() const
1412 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1413 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1415 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1417 int direction
, ascent
, descent
;
1418 XCharStruct overall
;
1419 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1420 &descent
, &overall
);
1421 // return XDEV2LOGREL(overall.ascent + overall.descent);
1422 return XDEV2LOGREL(ascent
+ descent
);
1425 void wxWindowDC::Clear()
1427 wxCHECK_RET( Ok(), "invalid dc" );
1432 m_window
->GetSize(&w
, &h
);
1434 if (m_window
&& m_window
->GetBackingPixmap())
1436 w
= m_window
->GetPixmapWidth();
1437 h
= m_window
->GetPixmapHeight();
1442 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1444 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1445 w
= memDC
->GetBitmap().GetWidth();
1446 h
= memDC
->GetBitmap().GetHeight();
1452 wxBrush saveBrush
= m_brush
;
1453 SetBrush (m_backgroundBrush
);
1455 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1457 if (m_window
&& m_window
->GetBackingPixmap())
1458 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1460 m_brush
= saveBrush
;
1463 void wxWindowDC::Clear(const wxRect
& rect
)
1465 wxCHECK_RET( Ok(), "invalid dc" );
1467 int x
= rect
.x
; int y
= rect
.y
;
1468 int w
= rect
.width
; int h
= rect
.height
;
1470 wxBrush saveBrush
= m_brush
;
1471 SetBrush (m_backgroundBrush
);
1473 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1475 if (m_window
&& m_window
->GetBackingPixmap())
1476 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1478 m_brush
= saveBrush
;
1481 void wxWindowDC::SetFont( const wxFont
&font
)
1483 wxCHECK_RET( Ok(), "invalid dc" );
1489 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1491 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1493 if (m_window
&& m_window
->GetBackingPixmap())
1494 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1499 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1501 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1502 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1504 if (m_window
&& m_window
->GetBackingPixmap())
1505 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1508 void wxWindowDC::SetPen( const wxPen
&pen
)
1510 wxCHECK_RET( Ok(), "invalid dc" );
1516 wxBitmap oldStipple
= m_currentStipple
;
1517 int oldStyle
= m_currentStyle
;
1518 int oldFill
= m_currentFill
;
1519 int old_pen_width
= m_currentPenWidth
;
1520 int old_pen_join
= m_currentPenJoin
;
1521 int old_pen_cap
= m_currentPenCap
;
1522 int old_pen_nb_dash
= m_currentPenDashCount
;
1523 wxMOTIFDash
*old_pen_dash
= m_currentPenDash
;
1525 wxColour oldPenColour
= m_currentColour
;
1526 m_currentColour
= m_pen
.GetColour ();
1527 m_currentStyle
= m_pen
.GetStyle ();
1528 m_currentFill
= m_pen
.GetStyle (); // TODO?
1529 m_currentPenWidth
= m_pen
.GetWidth ();
1530 m_currentPenJoin
= m_pen
.GetJoin ();
1531 m_currentPenCap
= m_pen
.GetCap ();
1532 m_currentPenDashCount
= m_pen
.GetDashCount();
1533 m_currentPenDash
= (wxMOTIFDash
*)m_pen
.GetDash();
1535 if (m_currentStyle
== wxSTIPPLE
)
1536 m_currentStipple
= * m_pen
.GetStipple ();
1538 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1539 oldFill
== m_currentFill
&&
1540 old_pen_join
== m_currentPenJoin
&&
1541 old_pen_cap
== m_currentPenCap
&&
1542 old_pen_nb_dash
== m_currentPenDashCount
&&
1543 old_pen_dash
== m_currentPenDash
&&
1544 old_pen_width
== m_currentPenWidth
);
1546 bool sameColour
= (oldPenColour
.Ok () &&
1547 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1548 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1549 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1550 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1552 if (!sameStyle
|| !GetOptimization())
1554 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1555 if (scaled_width
< 0)
1561 static const wxMOTIFDash dotted
[] = {2, 5};
1562 static const wxMOTIFDash short_dashed
[] = {4, 4};
1563 static const wxMOTIFDash long_dashed
[] = {4, 8};
1564 static const wxMOTIFDash dotted_dashed
[] = {6, 6, 2, 6};
1566 // We express dash pattern in pen width unit, so we are
1567 // independent of zoom factor and so on...
1569 const wxMOTIFDash
*req_dash
;
1571 switch (m_pen
.GetStyle ())
1574 req_nb_dash
= m_currentPenDashCount
;
1575 req_dash
= m_currentPenDash
;
1576 style
= LineOnOffDash
;
1581 style
= LineOnOffDash
;
1585 req_dash
= short_dashed
;
1586 style
= LineOnOffDash
;
1590 req_dash
= long_dashed
;
1591 style
= LineOnOffDash
;
1595 req_dash
= dotted_dashed
;
1596 style
= LineOnOffDash
;
1603 req_dash
= (wxMOTIFDash
*)NULL
;
1607 if (req_dash
&& req_nb_dash
)
1609 wxMOTIFDash
*real_req_dash
= new wxMOTIFDash
[req_nb_dash
];
1612 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1613 for (int i
= 0; i
< req_nb_dash
; i
++)
1614 real_req_dash
[i
] = req_dash
[i
] * factor
;
1615 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1617 if (m_window
&& m_window
->GetBackingPixmap())
1618 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1619 delete[]real_req_dash
;
1623 // No Memory. We use non-scaled dash pattern...
1624 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1626 if (m_window
&& m_window
->GetBackingPixmap())
1627 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1631 switch (m_pen
.GetCap ())
1633 case wxCAP_PROJECTING
:
1634 cap
= CapProjecting
;
1641 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1645 switch (m_pen
.GetJoin ())
1659 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1661 if (m_window
&& m_window
->GetBackingPixmap())
1662 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1665 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1669 oldStipple
= wxNullBitmap
; // For later reset!!
1671 switch (m_currentFill
)
1673 case wxBDIAGONAL_HATCH
:
1674 if (bdiag
== (Pixmap
) 0)
1675 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1676 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1677 bdiag_bits
, bdiag_width
, bdiag_height
);
1680 case wxFDIAGONAL_HATCH
:
1681 if (fdiag
== (Pixmap
) 0)
1682 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1683 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1684 fdiag_bits
, fdiag_width
, fdiag_height
);
1688 if (cross
== (Pixmap
) 0)
1689 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1690 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1691 cross_bits
, cross_width
, cross_height
);
1694 case wxHORIZONTAL_HATCH
:
1695 if (horiz
== (Pixmap
) 0)
1696 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1697 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1698 horiz_bits
, horiz_width
, horiz_height
);
1701 case wxVERTICAL_HATCH
:
1702 if (verti
== (Pixmap
) 0)
1703 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1704 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1705 verti_bits
, verti_width
, verti_height
);
1708 case wxCROSSDIAG_HATCH
:
1710 if (cdiag
== (Pixmap
) 0)
1711 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1712 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1713 cdiag_bits
, cdiag_width
, cdiag_height
);
1717 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1719 if (m_window
&& m_window
->GetBackingPixmap())
1720 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1722 else if (m_currentStipple
.Ok()
1723 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1725 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1727 if (m_window
&& m_window
->GetBackingPixmap())
1728 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1731 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1735 if (m_currentFill
== wxSTIPPLE
)
1736 fill_style
= FillStippled
;
1737 else if (IS_HATCH (m_currentFill
))
1738 fill_style
= FillStippled
;
1740 fill_style
= FillSolid
;
1741 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1742 if (m_window
&& m_window
->GetBackingPixmap())
1743 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1746 // must test m_logicalFunction, because it involves background!
1747 if (!sameColour
|| !GetOptimization()
1748 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1751 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1752 pixel
= m_backgroundPixel
;
1755 unsigned char red
= m_pen
.GetColour ().Red ();
1756 unsigned char blue
= m_pen
.GetColour ().Blue ();
1757 unsigned char green
= m_pen
.GetColour ().Green ();
1758 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1759 && green
== (unsigned char) 255)
1761 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1762 m_currentColour
= *wxWHITE
;
1763 m_pen
.GetColour().SetPixel(pixel
);
1764 m_currentColour
.SetPixel(pixel
);
1768 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1769 m_currentColour
= *wxBLACK
;
1770 m_pen
.GetColour().SetPixel(pixel
);
1775 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1776 m_currentColour
.SetPixel(pixel
);
1779 // Finally, set the GC to the required colour
1782 if (m_logicalFunction
== wxXOR
)
1785 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1786 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1787 if (m_window
&& m_window
->GetBackingPixmap())
1788 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1792 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1793 if (m_window
&& m_window
->GetBackingPixmap())
1794 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1799 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1804 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1806 wxCHECK_RET( Ok(), "invalid dc" );
1810 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1813 int oldFill
= m_currentFill
;
1814 wxBitmap oldStipple
= m_currentStipple
;
1816 m_autoSetting
|= 0x1;
1818 m_currentFill
= m_brush
.GetStyle ();
1819 if (m_currentFill
== wxSTIPPLE
)
1820 m_currentStipple
= * m_brush
.GetStipple ();
1822 wxColour
oldBrushColour(m_currentColour
);
1823 m_currentColour
= m_brush
.GetColour ();
1825 bool sameColour
= (oldBrushColour
.Ok () &&
1826 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1827 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1828 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1829 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1831 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1833 switch (brush
.GetStyle ())
1837 case wxBDIAGONAL_HATCH
:
1838 case wxCROSSDIAG_HATCH
:
1839 case wxFDIAGONAL_HATCH
:
1841 case wxHORIZONTAL_HATCH
:
1842 case wxVERTICAL_HATCH
:
1845 // Chris Breeze 23/07/97: use background mode to determine whether
1846 // fill style should be solid or transparent
1847 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1848 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1849 if (m_window
&& m_window
->GetBackingPixmap())
1850 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1855 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1856 if (m_window
&& m_window
->GetBackingPixmap())
1857 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1861 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1865 switch (m_currentFill
)
1867 case wxBDIAGONAL_HATCH
:
1868 if (bdiag
== (Pixmap
) 0)
1869 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1870 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1871 bdiag_bits
, bdiag_width
, bdiag_height
);
1874 case wxFDIAGONAL_HATCH
:
1875 if (fdiag
== (Pixmap
) 0)
1876 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1877 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1878 fdiag_bits
, fdiag_width
, fdiag_height
);
1882 if (cross
== (Pixmap
) 0)
1883 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1884 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1885 cross_bits
, cross_width
, cross_height
);
1888 case wxHORIZONTAL_HATCH
:
1889 if (horiz
== (Pixmap
) 0)
1890 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1891 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1892 horiz_bits
, horiz_width
, horiz_height
);
1895 case wxVERTICAL_HATCH
:
1896 if (verti
== (Pixmap
) 0)
1897 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1898 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1899 verti_bits
, verti_width
, verti_height
);
1902 case wxCROSSDIAG_HATCH
:
1904 if (cdiag
== (Pixmap
) 0)
1905 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1906 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1907 cdiag_bits
, cdiag_width
, cdiag_height
);
1911 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1913 if (m_window
&& m_window
->GetBackingPixmap())
1914 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1916 // X can forget the stipple value when resizing a window (apparently)
1917 // so always set the stipple.
1918 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1920 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1921 if (m_window
&& m_window
->GetBackingPixmap())
1922 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1925 // must test m_logicalFunction, because it involves background!
1926 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1931 // Policy - on a monochrome screen, all brushes are white,
1932 // except when they're REALLY black!!!
1933 unsigned char red
= m_brush
.GetColour ().Red ();
1934 unsigned char blue
= m_brush
.GetColour ().Blue ();
1935 unsigned char green
= m_brush
.GetColour ().Green ();
1937 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1938 && green
== (unsigned char) 0)
1940 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1941 m_currentColour
= *wxBLACK
;
1942 m_brush
.GetColour().SetPixel(pixel
);
1943 m_currentColour
.SetPixel(pixel
);
1947 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1948 m_currentColour
= *wxWHITE
;
1949 m_brush
.GetColour().SetPixel(pixel
);
1950 m_currentColour
.SetPixel(pixel
);
1953 // N.B. comment out the above line and uncomment the following lines
1954 // if you want non-white colours to be black on a monochrome display.
1956 if (red == (unsigned char )255 && blue == (unsigned char)255
1957 && green == (unsigned char)255)
1958 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1960 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1963 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1965 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1966 m_currentColour
.SetPixel(pixel
);
1970 // Finally, set the GC to the required colour
1971 if (m_logicalFunction
== wxXOR
)
1974 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1975 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1976 if (m_window
&& m_window
->GetBackingPixmap())
1977 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1981 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1982 if (m_window
&& m_window
->GetBackingPixmap())
1983 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1988 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1991 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1993 wxCHECK_RET( Ok(), "invalid dc" );
1995 m_backgroundBrush
= brush
;
1997 if (!m_backgroundBrush
.Ok())
2000 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
2002 // New behaviour, 10/2/99: setting the background brush of a DC
2003 // doesn't affect the window background colour.
2005 // XSetWindowBackground doesn't work for non-Window pixmaps
2006 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2007 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2010 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2011 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2012 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2013 if (m_window
&& m_window
->GetBackingPixmap())
2014 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2017 void wxWindowDC::SetLogicalFunction( int function
)
2019 wxCHECK_RET( Ok(), "invalid dc" );
2024 if (m_logicalFunction
== function
)
2030 x_function
= GXclear
;
2036 x_function
= GXinvert
;
2039 x_function
= GXorReverse
;
2042 x_function
= GXandReverse
;
2051 x_function
= GXandInverted
;
2054 x_function
= GXnoop
;
2060 x_function
= GXequiv
;
2063 x_function
= GXcopyInverted
;
2066 x_function
= GXorInverted
;
2069 x_function
= GXnand
;
2076 x_function
= GXcopy
;
2080 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2081 if (m_window
&& m_window
->GetBackingPixmap())
2082 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2084 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2085 /* MATTHEW: [9] Need to redo pen simply */
2086 m_autoSetting
|= 0x2;
2088 m_logicalFunction
= function
;
2092 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2094 wxCHECK_RET( Ok(), "invalid dc" );
2096 if (m_textForegroundColour
== col
)
2099 m_textForegroundColour
= col
;
2103 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2105 wxCHECK_RET( Ok(), "invalid dc" );
2107 if (m_textBackgroundColour
== col
)
2110 m_textBackgroundColour
= col
;
2111 if (!m_textBackgroundColour
.Ok())
2115 void wxWindowDC::SetBackgroundMode( int mode
)
2117 m_backgroundMode
= mode
;
2120 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2125 /* Use GetXColormap */
2126 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2127 (Colormap
) palette
.GetXColormap());
2129 /* Use wxGetMainColormap */
2130 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2131 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2136 void wxWindowDC::SetDCClipping()
2138 // m_userRegion is the region set by calling SetClippingRegion
2140 if (m_currentRegion
)
2141 XDestroyRegion ((Region
) m_currentRegion
);
2143 // We need to take into account
2144 // clipping imposed on a window by a repaint.
2145 // We'll combine it with the user region. But for now,
2146 // just use the currently-defined user clipping region.
2147 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2148 m_currentRegion
= (WXRegion
) XCreateRegion ();
2150 m_currentRegion
= (WXRegion
) NULL
;
2152 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2153 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2154 else if (m_userRegion
)
2155 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2156 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2157 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2158 (Region
) m_currentRegion
);
2160 if (m_currentRegion
)
2162 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2166 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2171 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2173 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2176 XDestroyRegion ((Region
) m_userRegion
);
2177 m_userRegion
= (WXRegion
) XCreateRegion ();
2181 r
.width
= XLOG2DEVREL(width
);
2182 r
.height
= YLOG2DEVREL(height
);
2183 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2187 // Needs to work differently for Pixmap: without this,
2188 // there's a nasty (Display*) m_display bug. 8/12/94
2189 if (m_window
&& m_window
->GetBackingPixmap())
2191 XRectangle rects
[1];
2192 rects
[0].x
= XLOG2DEV_2(x
);
2193 rects
[0].y
= YLOG2DEV_2(y
);
2194 rects
[0].width
= XLOG2DEVREL(width
);
2195 rects
[0].height
= YLOG2DEVREL(height
);
2196 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2200 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2202 wxRect box
= region
.GetBox();
2204 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2207 XDestroyRegion ((Region
) m_userRegion
);
2208 m_userRegion
= (WXRegion
) XCreateRegion ();
2210 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2214 // Needs to work differently for Pixmap: without this,
2215 // there's a nasty (Display*) m_display bug. 8/12/94
2216 if (m_window
&& m_window
->GetBackingPixmap())
2218 XRectangle rects
[1];
2219 rects
[0].x
= XLOG2DEV_2(box
.x
);
2220 rects
[0].y
= YLOG2DEV_2(box
.y
);
2221 rects
[0].width
= XLOG2DEVREL(box
.width
);
2222 rects
[0].height
= YLOG2DEVREL(box
.height
);
2223 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2228 void wxWindowDC::DestroyClippingRegion()
2230 wxDC::DestroyClippingRegion();
2233 XDestroyRegion ((Region
) m_userRegion
);
2234 m_userRegion
= NULL
;
2239 gc_val
.clip_mask
= None
;
2240 if (m_window
&& m_window
->GetBackingPixmap())
2241 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2244 // Resolution in pixels per logical inch
2245 wxSize
wxWindowDC::GetPPI() const
2247 return wxSize(100, 100);
2250 int wxWindowDC::GetDepth() const
2259 // ----------------------------------------------------------------------------
2261 // ----------------------------------------------------------------------------
2263 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2265 wxRegion
* region
= NULL
;
2267 // Combine all the update rects into a region
2268 const wxRectList
& updateRects(win
->GetUpdateRects());
2269 if ( updateRects
.GetCount() != 0 )
2271 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2273 node
= node
->GetNext() )
2275 wxRect
* rect
= node
->GetData();
2278 region
= new wxRegion(*rect
);
2280 // TODO: is this correct? In SetDCClipping above,
2281 // XIntersectRegion is used to combine paint and user
2282 // regions. XIntersectRegion appears to work in that case...
2283 region
->Union(*rect
);
2289 win
->GetClientSize(&cw
, &ch
);
2290 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2293 win
->SetUpdateRegion(*region
);
2295 wxRegion
& theRegion(win
->GetUpdateRegion());
2296 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2298 // Set the clipping region. Any user-defined region will be combined with this
2299 // one in SetDCClipping.
2300 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2305 wxPaintDC::~wxPaintDC()
2307 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2309 m_window
->ClearUpdateRegion();
2312 // ----------------------------------------------------------------------------
2313 // private functions
2314 // ----------------------------------------------------------------------------
2317 Used when copying between drawables on different (Display*) m_displays. Not
2318 very fast, but better than giving up.
2321 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2322 Drawable src
, Drawable dest
,
2325 unsigned int w
, unsigned int h
,
2326 int destx
, int desty
,
2327 bool more
, XImage
**cache
)
2329 XImage
*image
, *destimage
;
2330 Colormap destcm
, srccm
;
2331 static const int CACHE_SIZE
= 256;
2334 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2335 int k
, cache_pos
, all_cache
;
2337 if (!cache
|| !*cache
)
2338 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2342 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2344 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2345 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2350 for (i
= 0; i
< w
; i
++)
2351 for (j
= 0; j
< h
; j
++) {
2352 unsigned long pixel
;
2355 pixel
= XGetPixel(image
, i
, j
);
2356 for (k
= cache_pos
; k
--; )
2357 if (cachesrc
[k
] == pixel
) {
2358 pixel
= cachedest
[k
];
2362 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2363 if (cachesrc
[k
] == pixel
) {
2364 pixel
= cachedest
[k
];
2368 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2369 XQueryColor(src_display
, srccm
, &xcol
);
2370 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2372 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2374 if (++cache_pos
>= CACHE_SIZE
) {
2380 XPutPixel(destimage
, i
, j
, pixel
);
2383 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2384 XDestroyImage(destimage
);
2389 XDestroyImage(image
);
2394 /* Helper function for 16-bit fonts */
2395 static int str16len(const char *s
)
2399 while (s
[0] && s
[1]) {