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 #include "X11/Xutil.h"
57 #pragma message enable nosimpint
60 #include "wx/x11/private.h"
63 #include <float.h> // for M_PI
73 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
79 // Fudge factor (VZ: what??)
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
87 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
88 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
95 Drawable src
, Drawable dest
,
98 unsigned int w
, unsigned int h
,
100 bool more
, XImage
**cache
);
102 // ============================================================================
104 // ============================================================================
107 * compare two doubles and return the larger rounded
110 static int roundmax(double a
, double b
)
112 return (int)((a
> b
? a
: b
) + 0.5);
116 * compare two doubles and return the smaller rounded
119 static int roundmin(double a
, double b
)
121 return (int)((a
< b
? a
: b
) - 0.5);
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
129 wxWindowDC::wxWindowDC()
132 m_gcBacking
= (WXGC
) 0;
134 m_backgroundPixel
= -1;
135 m_currentPenWidth
= 1;
136 m_currentPenJoin
= -1;
137 m_currentPenDashCount
= -1;
138 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
141 // m_currentBkMode = wxTRANSPARENT;
142 m_colour
= wxColourDisplay();
143 m_display
= (WXDisplay
*) NULL
;
144 m_currentRegion
= (WXRegion
) 0;
145 m_userRegion
= (WXRegion
) 0;
146 m_pixmap
= (WXPixmap
) 0;
148 m_oldFont
= (WXFont
) 0;
151 wxWindowDC::wxWindowDC( wxWindow
*window
)
153 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
156 m_font
= window
->GetFont();
158 m_gcBacking
= (WXGC
) 0;
159 m_backgroundPixel
= -1;
160 m_currentPenWidth
= 1;
161 m_currentPenJoin
= -1;
162 m_currentPenDashCount
= -1;
163 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
166 // m_currentBkMode = wxTRANSPARENT;
167 m_colour
= wxColourDisplay();
168 m_currentRegion
= (WXRegion
) 0;
169 m_userRegion
= (WXRegion
) 0;
173 m_display
= window
->GetXDisplay();
174 m_pixmap
= window
->GetXWindow();
175 Display
* display
= (Display
*) m_display
;
177 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
180 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
181 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
182 gcvalues
.graphics_exposures
= False
;
183 gcvalues
.subwindow_mode
= IncludeInferiors
;
184 gcvalues
.line_width
= 1;
185 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
186 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
189 if (m_window
->GetBackingPixmap())
191 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
192 DefaultScreen (display
)),
193 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
197 m_backgroundPixel
= (int) gcvalues
.background
;
199 // Get the current Font so we can set it back later
201 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
202 m_oldFont
= (WXFont
) valReturn
.font
;
204 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
207 wxWindowDC::~wxWindowDC()
209 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
211 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
213 if (m_window
&& m_window
->GetBackingPixmap())
214 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
218 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
222 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
223 m_gcBacking
= (WXGC
) 0;
226 XDestroyRegion ((Region
) m_currentRegion
);
227 m_currentRegion
= (WXRegion
) 0;
230 XDestroyRegion ((Region
) m_userRegion
);
231 m_userRegion
= (WXRegion
) 0;
234 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
235 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
237 wxFAIL_MSG("not implemented");
240 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
242 // Generic (and therefore rather inefficient) method.
243 // Could be improved.
245 wxBitmap
bitmap(1, 1);
246 memdc
.SelectObject(bitmap
);
247 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
248 memdc
.SelectObject(wxNullBitmap
);
249 wxImage
image(bitmap
);
250 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
254 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
256 wxCHECK_RET( Ok(), "invalid dc" );
258 int x1d
, y1d
, x2d
, y2d
;
260 // FreeGetPixelCache();
270 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
272 if (m_window
&& m_window
->GetBackingPixmap())
273 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
274 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
275 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
277 CalcBoundingBox(x1
, y1
);
278 CalcBoundingBox(x2
, y2
);
281 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
283 wxCHECK_RET( Ok(), "invalid dc" );
288 int xx
= XLOG2DEV (x
);
289 int yy
= YLOG2DEV (y
);
291 wxDisplaySize (&ww
, &hh
);
292 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
294 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
297 if (m_window
&& m_window
->GetBackingPixmap())
301 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
304 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
310 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
312 wxCHECK_RET( Ok(), "invalid dc" );
314 // FreeGetPixelCache();
316 int xx1
= XLOG2DEV (x1
);
317 int yy1
= YLOG2DEV (y1
);
318 int xx2
= XLOG2DEV (x2
);
319 int yy2
= YLOG2DEV (y2
);
320 int xxc
= XLOG2DEV (xc
);
321 int yyc
= YLOG2DEV (yc
);
322 int xxc_2
= XLOG2DEV_2 (xc
);
323 int yyc_2
= YLOG2DEV_2 (yc
);
325 wxCoord dx
= xx1
- xxc
;
326 wxCoord dy
= yy1
- yyc
;
327 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
328 wxCoord r
= (wxCoord
) radius
;
330 double radius1
, radius2
;
332 if (xx1
== xx2
&& yy1
== yy2
)
337 else if (radius
== 0.0)
338 radius1
= radius2
= 0.0;
347 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
355 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
359 int alpha1
= (int) radius1
;
360 int alpha2
= (int) (radius2
- radius1
);
363 while (alpha2
> 360 * 64)
366 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
369 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
370 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
372 if (m_window
&& m_window
->GetBackingPixmap())
373 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
374 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
378 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
382 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
383 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
385 if (m_window
&& m_window
->GetBackingPixmap())
386 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
387 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
389 CalcBoundingBox (x1
, y1
);
390 CalcBoundingBox (x2
, y2
);
393 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
395 wxCHECK_RET( Ok(), "invalid dc" );
401 wd
= XLOG2DEVREL(width
);
402 hd
= YLOG2DEVREL(height
);
404 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
405 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
406 int start
= int(sa
*64);
407 int end
= int(ea
*64);
408 if (start
<0) start
+=360*64;
409 if (end
<0) end
+=360*64;
410 if (end
>start
) end
-=start
;
411 else end
+=360*64-start
;
413 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
415 m_autoSetting
= TRUE
; // must be reset
418 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
420 if (m_window
&& m_window
->GetBackingPixmap())
421 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
422 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
425 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
429 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
430 if (m_window
&& m_window
->GetBackingPixmap())
431 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
432 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
434 CalcBoundingBox (x
, y
);
435 CalcBoundingBox (x
+ width
, y
+ height
);
438 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
440 wxCHECK_RET( Ok(), "invalid dc" );
442 // FreeGetPixelCache();
444 if (m_pen
.Ok() && m_autoSetting
)
447 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
448 if (m_window
&& m_window
->GetBackingPixmap())
449 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
451 CalcBoundingBox (x
, y
);
454 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
456 wxCHECK_RET( Ok(), "invalid dc" );
458 // FreeGetPixelCache();
460 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
465 XPoint
*xpoints
= new XPoint
[n
];
468 for (i
= 0; i
< n
; i
++)
470 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
471 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
473 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
475 if (m_window
&& m_window
->GetBackingPixmap())
477 for (i
= 0; i
< n
; i
++)
479 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
480 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
482 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
488 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
489 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
491 wxCHECK_RET( Ok(), "invalid dc" );
493 // FreeGetPixelCache();
495 XPoint
*xpoints1
= new XPoint
[n
+ 1];
496 XPoint
*xpoints2
= new XPoint
[n
+ 1];
498 for (i
= 0; i
< n
; i
++)
500 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
501 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
502 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
503 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
504 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
507 // Close figure for XDrawLines (not needed for XFillPolygon)
508 xpoints1
[i
].x
= xpoints1
[0].x
;
509 xpoints1
[i
].y
= xpoints1
[0].y
;
510 xpoints2
[i
].x
= xpoints2
[0].x
;
511 xpoints2
[i
].y
= xpoints2
[0].y
;
513 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
516 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
517 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
518 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
519 if (m_window
&& m_window
->GetBackingPixmap())
521 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
522 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
523 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
524 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
528 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
532 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
534 if (m_window
&& m_window
->GetBackingPixmap())
535 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
542 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
544 wxCHECK_RET( Ok(), "invalid dc" );
546 // FreeGetPixelCache();
548 int xd
, yd
, wfd
, hfd
, wd
, hd
;
552 wfd
= XLOG2DEVREL(width
);
554 hfd
= YLOG2DEVREL(height
);
557 if (wfd
== 0 || hfd
== 0) return;
558 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
559 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
561 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
564 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
566 if (m_window
&& m_window
->GetBackingPixmap())
567 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
568 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
572 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
576 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
578 if (m_window
&& m_window
->GetBackingPixmap())
579 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
580 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
583 CalcBoundingBox (x
, y
);
584 CalcBoundingBox (x
+ width
, y
+ height
);
587 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
589 wxCHECK_RET( Ok(), "invalid dc" );
591 // FreeGetPixelCache();
593 // If radius is negative, it's a proportion of the smaller dimension.
595 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
597 int xd
= XLOG2DEV (x
);
598 int yd
= YLOG2DEV (y
);
599 int rd
= XLOG2DEVREL ((long) radius
);
600 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
601 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
606 // If radius is zero use DrawRectangle() instead to avoid
607 // X drawing errors with small radii
610 DrawRectangle( x
, y
, width
, height
);
614 // Draw nothing if transformed w or h is 0
615 if (wd
== 0 || hd
== 0) return;
617 // CMB: adjust size if outline is drawn otherwise the result is
618 // 1 pixel too wide and high
619 if (m_pen
.GetStyle() != wxTRANSPARENT
)
625 // CMB: ensure dd is not larger than rectangle otherwise we
626 // get an hour glass shape
627 if (rw_d
> wd
) rw_d
= wd
;
628 if (rw_d
> hd
) rw_d
= hd
;
631 // For backing pixmap
632 int xd2
= XLOG2DEV_2 (x
);
633 int yd2
= YLOG2DEV_2 (y
);
634 int rd2
= XLOG2DEVREL ((long) radius
);
635 int wd2
= XLOG2DEVREL (width
) ;
636 int hd2
= YLOG2DEVREL (height
) ;
641 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
645 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
647 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
650 // Arcs start from 3 o'clock, positive angles anticlockwise
652 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
653 rw_d
, rh_d
, 90 * 64, 90 * 64);
655 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
656 // rw_d, rh_d, 0, 90 * 64);
657 rw_d
, rh_d
, 0, 91 * 64);
659 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
661 // rw_d, rh_d, 270 * 64, 90 * 64);
662 rw_d
, rh_d
, 269 * 64, 92 * 64);
664 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
665 rw_d
, rh_d
, 180 * 64, 90 * 64);
667 if (m_window
&& m_window
->GetBackingPixmap())
669 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
670 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
671 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
672 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
674 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
675 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
676 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
677 xd2
+ wd2
- rw_d2
, yd2
,
678 // rw_d2, rh_d2, 0, 90 * 64);
679 rw_d2
, rh_d2
, 0, 91 * 64);
680 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
683 // rw_d2, rh_d2, 270 * 64, 90 * 64);
684 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
685 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
686 xd2
, yd2
+ hd2
- rh_d2
,
687 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
691 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
694 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
695 xd
+ wd
- rd
+ 1, yd
);
696 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
697 xd
+ wd
- rd
, yd
+ hd
);
699 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
701 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
702 xd
+ wd
, yd
+ hd
- rd
+ 1);
703 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
704 rw_d
, rh_d
, 90 * 64, 90 * 64);
705 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
706 // rw_d, rh_d, 0, 90 * 64);
707 rw_d
, rh_d
, 0, 91 * 64);
708 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
710 rw_d
, rh_d
, 269 * 64, 92 * 64);
711 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
712 rw_d
, rh_d
, 180 * 64, 90 * 64);
714 if (m_window
&& m_window
->GetBackingPixmap())
716 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
718 xd2
+ wd2
- rd2
+ 1, yd2
);
719 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
720 xd2
+ rd2
, yd2
+ hd2
,
721 xd2
+ wd2
- rd2
, yd2
+ hd2
);
723 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
725 xd2
, yd2
+ hd2
- rd2
);
726 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
727 xd2
+ wd2
, yd2
+ rd2
,
728 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
729 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
731 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
732 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
733 xd2
+ wd2
- rw_d2
, yd2
,
734 // rw_d2, rh_d2, 0, 90 * 64);
735 rw_d2
, rh_d2
, 0, 91 * 64);
736 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
739 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
740 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
741 xd2
, yd2
+ hd2
- rh_d2
,
742 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
745 CalcBoundingBox (x
, y
);
746 CalcBoundingBox (x
+ width
, y
+ height
);
751 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
753 wxCHECK_RET( Ok(), "invalid dc" );
755 // Check for negative width and height
768 // FreeGetPixelCache();
770 static const int angle
= 23040;
776 wd
= XLOG2DEVREL(width
) ;
777 hd
= YLOG2DEVREL(height
) ;
779 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
782 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
783 if (m_window
&& m_window
->GetBackingPixmap())
784 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
785 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
786 XLOG2DEVREL (width
) - WX_GC_CF
,
787 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
790 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
794 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
795 if (m_window
&& m_window
->GetBackingPixmap())
796 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
797 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
798 XLOG2DEVREL (width
) - WX_GC_CF
,
799 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
801 CalcBoundingBox (x
, y
);
802 CalcBoundingBox (x
+ width
, y
+ height
);
806 bool wxWindowDC::CanDrawBitmap() const
808 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
814 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
816 // FreeGetPixelCache();
818 // Be sure that foreground pixels (1) of
819 // the Icon will be painted with pen colour. [m_pen.SetColour()]
820 // Background pixels (0) will be painted with
821 // last selected background color. [::SetBackground]
822 if (m_pen
.Ok() && m_autoSetting
)
826 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
827 width
= icon
.GetWidth();
828 height
= icon
.GetHeight();
829 if (icon
.GetDisplay() == m_display
)
831 if (icon
.GetDepth() <= 1)
833 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
835 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
839 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
841 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
845 if (m_window
&& m_window
->GetBackingPixmap())
847 if (icon
.GetDepth() <= 1)
849 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
850 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
854 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
856 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
859 } else { /* Remote copy (different (Display*) m_displays) */
860 XImage
*cache
= NULL
;
861 if (m_window
&& m_window
->GetBackingPixmap())
862 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
863 (GC
) m_gcBacking
, 0, 0, width
, height
,
864 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
865 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
867 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
869 CalcBoundingBox (x
, y
);
873 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
874 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
875 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
876 wxCoord xsrcMask
, wxCoord ysrcMask
)
878 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
880 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
882 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
884 // FreeGetPixelCache();
886 // Be sure that foreground pixels (1) of the Icon will be painted with pen
887 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
888 // last selected background color. [::SetBackground]
889 if (m_pen
.Ok() && m_autoSetting
)
892 // Do bitmap scaling if necessary
894 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
895 Pixmap sourcePixmap
= (Pixmap
) NULL
;
896 double scaleX
, scaleY
;
897 GetUserScale(& scaleX
, & scaleY
);
899 /* TODO: use the mask origin when drawing transparently */
900 if (xsrcMask
== -1 && ysrcMask
== -1)
902 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
905 // Sorry, can't scale masks just yet
906 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
908 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
909 wxBitmap
& bitmap
= memDC
->GetBitmap();
911 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
913 wxImage
image(bitmap
);
916 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
920 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
921 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
923 image
= image
.Scale(scaledW
, scaledH
);
924 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
925 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
929 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
931 if (m_pixmap
&& sourcePixmap
)
934 int orig
= m_logicalFunction
;
936 SetLogicalFunction (rop
);
938 if (m_display
!= sourceDC
->m_display
)
940 XImage
*cache
= NULL
;
942 if (m_window
&& m_window
->GetBackingPixmap())
943 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
944 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
946 source
->LogicalToDeviceX (xsrc
),
947 source
->LogicalToDeviceY (ysrc
),
948 source
->LogicalToDeviceXRel(width
),
949 source
->LogicalToDeviceYRel(height
),
950 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
953 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
955 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
956 wxBitmap
& sel
= memDC
->GetBitmap();
957 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
959 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
960 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
964 XCopyRemote((Display
*) sourceDC
->m_display
, (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
),
974 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
975 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
980 if (m_window
&& m_window
->GetBackingPixmap())
982 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
983 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
985 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
986 source
->LogicalToDeviceX (xsrc
),
987 source
->LogicalToDeviceY (ysrc
),
988 source
->LogicalToDeviceXRel(width
),
989 source
->LogicalToDeviceYRel(height
),
990 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
994 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
995 source
->LogicalToDeviceX (xsrc
),
996 source
->LogicalToDeviceY (ysrc
),
997 source
->LogicalToDeviceXRel(width
),
998 source
->LogicalToDeviceYRel(height
),
999 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
1002 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1004 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1005 wxBitmap
& sel
= memDC
->GetBitmap();
1006 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1008 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1009 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1013 // Check if we're copying from a mono bitmap
1014 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1015 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1017 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1018 source
->LogicalToDeviceX (xsrc
),
1019 source
->LogicalToDeviceY (ysrc
),
1020 source
->LogicalToDeviceXRel(width
),
1021 source
->LogicalToDeviceYRel(height
),
1022 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1026 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1027 source
->LogicalToDeviceX (xsrc
),
1028 source
->LogicalToDeviceY (ysrc
),
1029 source
->LogicalToDeviceXRel(width
),
1030 source
->LogicalToDeviceYRel(height
),
1031 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1036 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1037 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1040 } /* Remote/local (Display*) m_display */
1041 CalcBoundingBox (xdest
, ydest
);
1042 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1044 SetLogicalFunction(orig
);
1046 if (scaledBitmap
) delete scaledBitmap
;
1050 if (scaledBitmap
) delete scaledBitmap
;
1055 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1057 wxCHECK_RET( Ok(), "invalid dc" );
1059 // Since X draws from the baseline of the text, must add the text height
1065 slen
= strlen(text
);
1069 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1070 int direction
, descent
;
1071 XCharStruct overall_return
;
1074 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1075 &ascent
, &descent
, &overall_return
);
1078 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1079 &ascent
, &descent
, &overall_return
);
1081 cx
= overall_return
.width
;
1082 cy
= ascent
+ descent
;
1085 // First draw a rectangle representing the text background, if a text
1086 // background is specified
1087 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1089 wxColour oldPenColour
= m_currentColour
;
1090 m_currentColour
= m_textBackgroundColour
;
1091 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1092 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1093 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1094 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1096 // This separation of the big && test required for gcc2.7/HP UX 9.02
1097 // or pixel value can be corrupted!
1098 sameColour
= (sameColour
&&
1099 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1101 if (!sameColour
|| !GetOptimization())
1103 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1104 m_currentColour
= m_textBackgroundColour
;
1106 // Set the GC to the required colour
1109 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1110 if (m_window
&& m_window
->GetBackingPixmap())
1111 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1115 m_textBackgroundColour
= oldPenColour
;
1117 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1118 if (m_window
&& m_window
->GetBackingPixmap())
1119 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1120 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1123 // Now set the text foreground and draw the text
1124 if (m_textForegroundColour
.Ok ())
1126 wxColour oldPenColour
= m_currentColour
;
1127 m_currentColour
= m_textForegroundColour
;
1128 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1129 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1130 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1131 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1132 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1134 if (!sameColour
|| !GetOptimization())
1137 if (!m_colour
) // Mono display
1139 // Unless foreground is really white, draw it in black
1140 unsigned char red
= m_textForegroundColour
.Red ();
1141 unsigned char blue
= m_textForegroundColour
.Blue ();
1142 unsigned char green
= m_textForegroundColour
.Green ();
1143 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1144 && green
== (unsigned char) 255)
1146 m_currentColour
= *wxWHITE
;
1147 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1148 m_currentColour
.SetPixel(pixel
);
1149 m_textForegroundColour
.SetPixel(pixel
);
1153 m_currentColour
= *wxBLACK
;
1154 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1155 m_currentColour
.SetPixel(pixel
);
1156 m_textForegroundColour
.SetPixel(pixel
);
1161 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1162 m_currentColour
.SetPixel(pixel
);
1165 // Set the GC to the required colour
1168 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1169 if (m_window
&& m_window
->GetBackingPixmap())
1170 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1174 m_textForegroundColour
= oldPenColour
;
1177 // We need to add the ascent, not the whole height, since X draws at the
1178 // point above the descender.
1181 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1182 (XChar2b
*)(char*) (const char*) text
, slen
);
1185 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1187 if (m_window
&& m_window
->GetBackingPixmap()) {
1190 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1191 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1192 (XChar2b
*)(char*) (const char*) text
, slen
);
1195 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1196 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1200 GetTextExtent (text
, &w
, &h
);
1201 CalcBoundingBox (x
+ w
, y
+ h
);
1202 CalcBoundingBox (x
, y
);
1205 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1209 DrawText(text
, x
, y
);
1213 wxCHECK_RET( Ok(), "invalid dc" );
1215 // Since X draws from the baseline of the text, must add the text height
1221 slen
= strlen(text
);
1225 // Calculate text extent.
1226 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1227 int direction
, descent
;
1228 XCharStruct overall_return
;
1231 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1232 &ascent
, &descent
, &overall_return
);
1235 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1236 &ascent
, &descent
, &overall_return
);
1238 cx
= overall_return
.width
;
1239 cy
= ascent
+ descent
;
1242 wxBitmap
src(cx
, cy
);
1244 dc
.SelectObject(src
);
1245 dc
.SetFont(GetFont());
1246 dc
.SetBackground(*wxWHITE_BRUSH
);
1247 dc
.SetBrush(*wxBLACK_BRUSH
);
1249 dc
.DrawText(text
, 0, 0);
1250 dc
.SetFont(wxNullFont
);
1252 // Calculate the size of the rotated bounding box.
1253 double dx
= cos(angle
/ 180.0 * M_PI
);
1254 double dy
= sin(angle
/ 180.0 * M_PI
);
1255 double x4
= -cy
* dy
;
1256 double y4
= cy
* dx
;
1257 double x3
= cx
* dx
;
1258 double y3
= cx
* dy
;
1259 double x2
= x3
+ x4
;
1260 double y2
= y3
+ y4
;
1264 // Create image from the source bitmap after writing the text into it.
1267 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1268 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1269 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1270 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1272 // This rotates counterclockwise around the top left corner.
1273 for (int rx
= minx
; rx
< maxx
; rx
++)
1275 for (int ry
= miny
; ry
< maxy
; ry
++)
1277 // transform dest coords to source coords
1278 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1279 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1280 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1282 // draw black pixels, ignore white ones (i.e. transparent b/g)
1283 if (image
.GetRed(sx
, sy
) == 0)
1285 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1290 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1297 // First draw a rectangle representing the text background, if a text
1298 // background is specified
1299 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1301 wxColour oldPenColour
= m_currentColour
;
1302 m_currentColour
= m_textBackgroundColour
;
1303 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1304 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1305 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1306 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1308 // This separation of the big && test required for gcc2.7/HP UX 9.02
1309 // or pixel value can be corrupted!
1310 sameColour
= (sameColour
&&
1311 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1313 if (!sameColour
|| !GetOptimization())
1315 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1316 m_currentColour
= m_textBackgroundColour
;
1318 // Set the GC to the required colour
1321 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1322 if (m_window
&& m_window
->GetBackingPixmap())
1323 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1327 m_textBackgroundColour
= oldPenColour
;
1329 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1330 if (m_window
&& m_window
->GetBackingPixmap())
1331 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1332 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1337 // XXX use pixmap size
1338 GetTextExtent (text
, &w
, &h
);
1339 CalcBoundingBox (x
+ w
, y
+ h
);
1340 CalcBoundingBox (x
, y
);
1343 bool wxWindowDC::CanGetTextExtent() const
1348 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1349 wxCoord
*descent
, wxCoord
*externalLeading
,
1350 wxFont
*font
) const
1352 wxCHECK_RET( Ok(), "invalid dc" );
1354 wxFont
* theFont
= font
;
1356 theFont
= (wxFont
*)&m_font
; // const_cast
1360 // TODO: this should be an error log function
1361 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1363 if (width
) *width
= -1;
1364 if (height
) *height
= -1;
1368 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1370 int direction
, ascent
, descent2
;
1371 XCharStruct overall
;
1376 slen
= str16len(string
);
1379 slen
= strlen(string
);
1383 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1384 &ascent
, &descent2
, &overall
);
1387 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1388 &ascent
, &descent2
, &overall
);
1390 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1391 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1393 *descent
= descent2
;
1394 if (externalLeading
)
1395 *externalLeading
= 0;
1398 wxCoord
wxWindowDC::GetCharWidth() const
1400 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1401 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1403 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1405 int direction
, ascent
, descent
;
1406 XCharStruct overall
;
1407 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1408 &descent
, &overall
);
1409 return XDEV2LOGREL(overall
.width
);
1412 wxCoord
wxWindowDC::GetCharHeight() const
1414 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1415 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1417 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1419 int direction
, ascent
, descent
;
1420 XCharStruct overall
;
1421 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1422 &descent
, &overall
);
1423 // return XDEV2LOGREL(overall.ascent + overall.descent);
1424 return XDEV2LOGREL(ascent
+ descent
);
1427 void wxWindowDC::Clear()
1429 wxCHECK_RET( Ok(), "invalid dc" );
1434 m_window
->GetSize(&w
, &h
);
1436 if (m_window
&& m_window
->GetBackingPixmap())
1438 w
= m_window
->GetPixmapWidth();
1439 h
= m_window
->GetPixmapHeight();
1444 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1446 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1447 w
= memDC
->GetBitmap().GetWidth();
1448 h
= memDC
->GetBitmap().GetHeight();
1454 wxBrush saveBrush
= m_brush
;
1455 SetBrush (m_backgroundBrush
);
1457 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1459 if (m_window
&& m_window
->GetBackingPixmap())
1460 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1462 m_brush
= saveBrush
;
1465 void wxWindowDC::Clear(const wxRect
& rect
)
1467 wxCHECK_RET( Ok(), "invalid dc" );
1469 int x
= rect
.x
; int y
= rect
.y
;
1470 int w
= rect
.width
; int h
= rect
.height
;
1472 wxBrush saveBrush
= m_brush
;
1473 SetBrush (m_backgroundBrush
);
1475 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1477 if (m_window
&& m_window
->GetBackingPixmap())
1478 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1480 m_brush
= saveBrush
;
1483 void wxWindowDC::SetFont( const wxFont
&font
)
1485 wxCHECK_RET( Ok(), "invalid dc" );
1491 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1493 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1495 if (m_window
&& m_window
->GetBackingPixmap())
1496 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1501 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1503 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1504 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1506 if (m_window
&& m_window
->GetBackingPixmap())
1507 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1510 void wxWindowDC::SetPen( const wxPen
&pen
)
1512 wxCHECK_RET( Ok(), "invalid dc" );
1518 wxBitmap oldStipple
= m_currentStipple
;
1519 int oldStyle
= m_currentStyle
;
1520 int oldFill
= m_currentFill
;
1521 int old_pen_width
= m_currentPenWidth
;
1522 int old_pen_join
= m_currentPenJoin
;
1523 int old_pen_cap
= m_currentPenCap
;
1524 int old_pen_nb_dash
= m_currentPenDashCount
;
1525 wxMOTIFDash
*old_pen_dash
= m_currentPenDash
;
1527 wxColour oldPenColour
= m_currentColour
;
1528 m_currentColour
= m_pen
.GetColour ();
1529 m_currentStyle
= m_pen
.GetStyle ();
1530 m_currentFill
= m_pen
.GetStyle (); // TODO?
1531 m_currentPenWidth
= m_pen
.GetWidth ();
1532 m_currentPenJoin
= m_pen
.GetJoin ();
1533 m_currentPenCap
= m_pen
.GetCap ();
1534 m_currentPenDashCount
= m_pen
.GetDashCount();
1535 m_currentPenDash
= (wxMOTIFDash
*)m_pen
.GetDash();
1537 if (m_currentStyle
== wxSTIPPLE
)
1538 m_currentStipple
= * m_pen
.GetStipple ();
1540 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1541 oldFill
== m_currentFill
&&
1542 old_pen_join
== m_currentPenJoin
&&
1543 old_pen_cap
== m_currentPenCap
&&
1544 old_pen_nb_dash
== m_currentPenDashCount
&&
1545 old_pen_dash
== m_currentPenDash
&&
1546 old_pen_width
== m_currentPenWidth
);
1548 bool sameColour
= (oldPenColour
.Ok () &&
1549 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1550 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1551 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1552 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1554 if (!sameStyle
|| !GetOptimization())
1556 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1557 if (scaled_width
< 0)
1563 static const wxMOTIFDash dotted
[] = {2, 5};
1564 static const wxMOTIFDash short_dashed
[] = {4, 4};
1565 static const wxMOTIFDash long_dashed
[] = {4, 8};
1566 static const wxMOTIFDash dotted_dashed
[] = {6, 6, 2, 6};
1568 // We express dash pattern in pen width unit, so we are
1569 // independent of zoom factor and so on...
1571 const wxMOTIFDash
*req_dash
;
1573 switch (m_pen
.GetStyle ())
1576 req_nb_dash
= m_currentPenDashCount
;
1577 req_dash
= m_currentPenDash
;
1578 style
= LineOnOffDash
;
1583 style
= LineOnOffDash
;
1587 req_dash
= short_dashed
;
1588 style
= LineOnOffDash
;
1592 req_dash
= long_dashed
;
1593 style
= LineOnOffDash
;
1597 req_dash
= dotted_dashed
;
1598 style
= LineOnOffDash
;
1605 req_dash
= (wxMOTIFDash
*)NULL
;
1609 if (req_dash
&& req_nb_dash
)
1611 wxMOTIFDash
*real_req_dash
= new wxMOTIFDash
[req_nb_dash
];
1614 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1615 for (int i
= 0; i
< req_nb_dash
; i
++)
1616 real_req_dash
[i
] = req_dash
[i
] * factor
;
1617 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1619 if (m_window
&& m_window
->GetBackingPixmap())
1620 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1621 delete[]real_req_dash
;
1625 // No Memory. We use non-scaled dash pattern...
1626 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1628 if (m_window
&& m_window
->GetBackingPixmap())
1629 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1633 switch (m_pen
.GetCap ())
1635 case wxCAP_PROJECTING
:
1636 cap
= CapProjecting
;
1643 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1647 switch (m_pen
.GetJoin ())
1661 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1663 if (m_window
&& m_window
->GetBackingPixmap())
1664 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1667 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1671 oldStipple
= wxNullBitmap
; // For later reset!!
1673 switch (m_currentFill
)
1675 case wxBDIAGONAL_HATCH
:
1676 if (bdiag
== (Pixmap
) 0)
1677 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1678 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1679 bdiag_bits
, bdiag_width
, bdiag_height
);
1682 case wxFDIAGONAL_HATCH
:
1683 if (fdiag
== (Pixmap
) 0)
1684 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1685 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1686 fdiag_bits
, fdiag_width
, fdiag_height
);
1690 if (cross
== (Pixmap
) 0)
1691 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1692 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1693 cross_bits
, cross_width
, cross_height
);
1696 case wxHORIZONTAL_HATCH
:
1697 if (horiz
== (Pixmap
) 0)
1698 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1699 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1700 horiz_bits
, horiz_width
, horiz_height
);
1703 case wxVERTICAL_HATCH
:
1704 if (verti
== (Pixmap
) 0)
1705 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1706 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1707 verti_bits
, verti_width
, verti_height
);
1710 case wxCROSSDIAG_HATCH
:
1712 if (cdiag
== (Pixmap
) 0)
1713 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1714 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1715 cdiag_bits
, cdiag_width
, cdiag_height
);
1719 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1721 if (m_window
&& m_window
->GetBackingPixmap())
1722 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1724 else if (m_currentStipple
.Ok()
1725 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1727 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1729 if (m_window
&& m_window
->GetBackingPixmap())
1730 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1733 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1737 if (m_currentFill
== wxSTIPPLE
)
1738 fill_style
= FillStippled
;
1739 else if (IS_HATCH (m_currentFill
))
1740 fill_style
= FillStippled
;
1742 fill_style
= FillSolid
;
1743 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1744 if (m_window
&& m_window
->GetBackingPixmap())
1745 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1748 // must test m_logicalFunction, because it involves background!
1749 if (!sameColour
|| !GetOptimization()
1750 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1753 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1754 pixel
= m_backgroundPixel
;
1757 unsigned char red
= m_pen
.GetColour ().Red ();
1758 unsigned char blue
= m_pen
.GetColour ().Blue ();
1759 unsigned char green
= m_pen
.GetColour ().Green ();
1760 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1761 && green
== (unsigned char) 255)
1763 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1764 m_currentColour
= *wxWHITE
;
1765 m_pen
.GetColour().SetPixel(pixel
);
1766 m_currentColour
.SetPixel(pixel
);
1770 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1771 m_currentColour
= *wxBLACK
;
1772 m_pen
.GetColour().SetPixel(pixel
);
1777 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1778 m_currentColour
.SetPixel(pixel
);
1781 // Finally, set the GC to the required colour
1784 if (m_logicalFunction
== wxXOR
)
1787 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1788 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1789 if (m_window
&& m_window
->GetBackingPixmap())
1790 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1794 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1795 if (m_window
&& m_window
->GetBackingPixmap())
1796 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1801 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1806 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1808 wxCHECK_RET( Ok(), "invalid dc" );
1812 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1815 int oldFill
= m_currentFill
;
1816 wxBitmap oldStipple
= m_currentStipple
;
1818 m_autoSetting
|= 0x1;
1820 m_currentFill
= m_brush
.GetStyle ();
1821 if (m_currentFill
== wxSTIPPLE
)
1822 m_currentStipple
= * m_brush
.GetStipple ();
1824 wxColour
oldBrushColour(m_currentColour
);
1825 m_currentColour
= m_brush
.GetColour ();
1827 bool sameColour
= (oldBrushColour
.Ok () &&
1828 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1829 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1830 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1831 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1833 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1835 switch (brush
.GetStyle ())
1839 case wxBDIAGONAL_HATCH
:
1840 case wxCROSSDIAG_HATCH
:
1841 case wxFDIAGONAL_HATCH
:
1843 case wxHORIZONTAL_HATCH
:
1844 case wxVERTICAL_HATCH
:
1847 // Chris Breeze 23/07/97: use background mode to determine whether
1848 // fill style should be solid or transparent
1849 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1850 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1851 if (m_window
&& m_window
->GetBackingPixmap())
1852 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1857 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1858 if (m_window
&& m_window
->GetBackingPixmap())
1859 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1863 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1867 switch (m_currentFill
)
1869 case wxBDIAGONAL_HATCH
:
1870 if (bdiag
== (Pixmap
) 0)
1871 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1872 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1873 bdiag_bits
, bdiag_width
, bdiag_height
);
1876 case wxFDIAGONAL_HATCH
:
1877 if (fdiag
== (Pixmap
) 0)
1878 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1879 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1880 fdiag_bits
, fdiag_width
, fdiag_height
);
1884 if (cross
== (Pixmap
) 0)
1885 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1886 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1887 cross_bits
, cross_width
, cross_height
);
1890 case wxHORIZONTAL_HATCH
:
1891 if (horiz
== (Pixmap
) 0)
1892 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1893 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1894 horiz_bits
, horiz_width
, horiz_height
);
1897 case wxVERTICAL_HATCH
:
1898 if (verti
== (Pixmap
) 0)
1899 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1900 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1901 verti_bits
, verti_width
, verti_height
);
1904 case wxCROSSDIAG_HATCH
:
1906 if (cdiag
== (Pixmap
) 0)
1907 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1908 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1909 cdiag_bits
, cdiag_width
, cdiag_height
);
1913 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1915 if (m_window
&& m_window
->GetBackingPixmap())
1916 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1918 // X can forget the stipple value when resizing a window (apparently)
1919 // so always set the stipple.
1920 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1922 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1923 if (m_window
&& m_window
->GetBackingPixmap())
1924 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1927 // must test m_logicalFunction, because it involves background!
1928 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1933 // Policy - on a monochrome screen, all brushes are white,
1934 // except when they're REALLY black!!!
1935 unsigned char red
= m_brush
.GetColour ().Red ();
1936 unsigned char blue
= m_brush
.GetColour ().Blue ();
1937 unsigned char green
= m_brush
.GetColour ().Green ();
1939 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1940 && green
== (unsigned char) 0)
1942 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1943 m_currentColour
= *wxBLACK
;
1944 m_brush
.GetColour().SetPixel(pixel
);
1945 m_currentColour
.SetPixel(pixel
);
1949 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1950 m_currentColour
= *wxWHITE
;
1951 m_brush
.GetColour().SetPixel(pixel
);
1952 m_currentColour
.SetPixel(pixel
);
1955 // N.B. comment out the above line and uncomment the following lines
1956 // if you want non-white colours to be black on a monochrome display.
1958 if (red == (unsigned char )255 && blue == (unsigned char)255
1959 && green == (unsigned char)255)
1960 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1962 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1965 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1967 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1968 m_currentColour
.SetPixel(pixel
);
1972 // Finally, set the GC to the required colour
1973 if (m_logicalFunction
== wxXOR
)
1976 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1977 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1978 if (m_window
&& m_window
->GetBackingPixmap())
1979 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1983 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1984 if (m_window
&& m_window
->GetBackingPixmap())
1985 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1990 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1993 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1995 wxCHECK_RET( Ok(), "invalid dc" );
1997 m_backgroundBrush
= brush
;
1999 if (!m_backgroundBrush
.Ok())
2002 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
2004 // New behaviour, 10/2/99: setting the background brush of a DC
2005 // doesn't affect the window background colour.
2007 // XSetWindowBackground doesn't work for non-Window pixmaps
2008 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2009 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2012 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2013 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2014 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2015 if (m_window
&& m_window
->GetBackingPixmap())
2016 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2019 void wxWindowDC::SetLogicalFunction( int function
)
2021 wxCHECK_RET( Ok(), "invalid dc" );
2026 if (m_logicalFunction
== function
)
2032 x_function
= GXclear
;
2038 x_function
= GXinvert
;
2041 x_function
= GXorReverse
;
2044 x_function
= GXandReverse
;
2053 x_function
= GXandInverted
;
2056 x_function
= GXnoop
;
2062 x_function
= GXequiv
;
2065 x_function
= GXcopyInverted
;
2068 x_function
= GXorInverted
;
2071 x_function
= GXnand
;
2078 x_function
= GXcopy
;
2082 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2083 if (m_window
&& m_window
->GetBackingPixmap())
2084 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2086 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2087 /* MATTHEW: [9] Need to redo pen simply */
2088 m_autoSetting
|= 0x2;
2090 m_logicalFunction
= function
;
2094 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2096 wxCHECK_RET( Ok(), "invalid dc" );
2098 if (m_textForegroundColour
== col
)
2101 m_textForegroundColour
= col
;
2105 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2107 wxCHECK_RET( Ok(), "invalid dc" );
2109 if (m_textBackgroundColour
== col
)
2112 m_textBackgroundColour
= col
;
2113 if (!m_textBackgroundColour
.Ok())
2117 void wxWindowDC::SetBackgroundMode( int mode
)
2119 m_backgroundMode
= mode
;
2122 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2127 /* Use GetXColormap */
2128 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2129 (Colormap
) palette
.GetXColormap());
2131 /* Use wxGetMainColormap */
2132 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2133 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2138 void wxWindowDC::SetDCClipping()
2140 // m_userRegion is the region set by calling SetClippingRegion
2142 if (m_currentRegion
)
2143 XDestroyRegion ((Region
) m_currentRegion
);
2145 // We need to take into account
2146 // clipping imposed on a window by a repaint.
2147 // We'll combine it with the user region. But for now,
2148 // just use the currently-defined user clipping region.
2149 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2150 m_currentRegion
= (WXRegion
) XCreateRegion ();
2152 m_currentRegion
= (WXRegion
) NULL
;
2154 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2155 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2156 else if (m_userRegion
)
2157 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2158 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2159 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2160 (Region
) m_currentRegion
);
2162 if (m_currentRegion
)
2164 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2168 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2173 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2175 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2178 XDestroyRegion ((Region
) m_userRegion
);
2179 m_userRegion
= (WXRegion
) XCreateRegion ();
2183 r
.width
= XLOG2DEVREL(width
);
2184 r
.height
= YLOG2DEVREL(height
);
2185 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2189 // Needs to work differently for Pixmap: without this,
2190 // there's a nasty (Display*) m_display bug. 8/12/94
2191 if (m_window
&& m_window
->GetBackingPixmap())
2193 XRectangle rects
[1];
2194 rects
[0].x
= XLOG2DEV_2(x
);
2195 rects
[0].y
= YLOG2DEV_2(y
);
2196 rects
[0].width
= XLOG2DEVREL(width
);
2197 rects
[0].height
= YLOG2DEVREL(height
);
2198 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2202 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2204 wxRect box
= region
.GetBox();
2206 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2209 XDestroyRegion ((Region
) m_userRegion
);
2210 m_userRegion
= (WXRegion
) XCreateRegion ();
2212 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2216 // Needs to work differently for Pixmap: without this,
2217 // there's a nasty (Display*) m_display bug. 8/12/94
2218 if (m_window
&& m_window
->GetBackingPixmap())
2220 XRectangle rects
[1];
2221 rects
[0].x
= XLOG2DEV_2(box
.x
);
2222 rects
[0].y
= YLOG2DEV_2(box
.y
);
2223 rects
[0].width
= XLOG2DEVREL(box
.width
);
2224 rects
[0].height
= YLOG2DEVREL(box
.height
);
2225 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2230 void wxWindowDC::DestroyClippingRegion()
2232 wxDC::DestroyClippingRegion();
2235 XDestroyRegion ((Region
) m_userRegion
);
2236 m_userRegion
= NULL
;
2241 gc_val
.clip_mask
= None
;
2242 if (m_window
&& m_window
->GetBackingPixmap())
2243 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2246 // Resolution in pixels per logical inch
2247 wxSize
wxWindowDC::GetPPI() const
2249 return wxSize(100, 100);
2252 int wxWindowDC::GetDepth() const
2261 // ----------------------------------------------------------------------------
2263 // ----------------------------------------------------------------------------
2265 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2267 wxRegion
* region
= NULL
;
2269 // Combine all the update rects into a region
2270 const wxRectList
& updateRects(win
->GetUpdateRects());
2271 if ( updateRects
.GetCount() != 0 )
2273 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2275 node
= node
->GetNext() )
2277 wxRect
* rect
= node
->GetData();
2280 region
= new wxRegion(*rect
);
2282 // TODO: is this correct? In SetDCClipping above,
2283 // XIntersectRegion is used to combine paint and user
2284 // regions. XIntersectRegion appears to work in that case...
2285 region
->Union(*rect
);
2291 win
->GetClientSize(&cw
, &ch
);
2292 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2295 win
->SetUpdateRegion(*region
);
2297 wxRegion
& theRegion(win
->GetUpdateRegion());
2298 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2300 // Set the clipping region. Any user-defined region will be combined with this
2301 // one in SetDCClipping.
2302 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2307 wxPaintDC::~wxPaintDC()
2309 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2311 m_window
->ClearUpdateRegion();
2314 // ----------------------------------------------------------------------------
2315 // private functions
2316 // ----------------------------------------------------------------------------
2319 Used when copying between drawables on different (Display*) m_displays. Not
2320 very fast, but better than giving up.
2323 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2324 Drawable src
, Drawable dest
,
2327 unsigned int w
, unsigned int h
,
2328 int destx
, int desty
,
2329 bool more
, XImage
**cache
)
2331 XImage
*image
, *destimage
;
2332 Colormap destcm
, srccm
;
2333 static const int CACHE_SIZE
= 256;
2336 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2337 int k
, cache_pos
, all_cache
;
2339 if (!cache
|| !*cache
)
2340 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2344 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2346 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2347 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2352 for (i
= 0; i
< w
; i
++)
2353 for (j
= 0; j
< h
; j
++) {
2354 unsigned long pixel
;
2357 pixel
= XGetPixel(image
, i
, j
);
2358 for (k
= cache_pos
; k
--; )
2359 if (cachesrc
[k
] == pixel
) {
2360 pixel
= cachedest
[k
];
2364 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2365 if (cachesrc
[k
] == pixel
) {
2366 pixel
= cachedest
[k
];
2370 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2371 XQueryColor(src_display
, srccm
, &xcol
);
2372 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2374 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2376 if (++cache_pos
>= CACHE_SIZE
) {
2382 XPutPixel(destimage
, i
, j
, pixel
);
2385 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2386 XDestroyImage(destimage
);
2391 XDestroyImage(image
);
2396 /* Helper function for 16-bit fonts */
2397 static int str16len(const char *s
)
2401 while (s
[0] && s
[1]) {