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"
53 #pragma message disable nosimpint
57 #pragma message enable nosimpint
60 #include "wx/motif/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 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
235 const wxColour
& col
, int style
);
237 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
238 const wxColour
& col
, int style
)
240 return wxDoFloodFill(this, x
, y
, col
, style
);
243 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
245 // Generic (and therefore rather inefficient) method.
246 // Could be improved.
248 wxBitmap
bitmap(1, 1);
249 memdc
.SelectObject(bitmap
);
250 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
251 memdc
.SelectObject(wxNullBitmap
);
252 wxImage
image(bitmap
);
253 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
257 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
259 wxCHECK_RET( Ok(), "invalid dc" );
261 int x1d
, y1d
, x2d
, y2d
;
263 // FreeGetPixelCache();
273 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
275 if (m_window
&& m_window
->GetBackingPixmap())
276 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
277 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
278 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
280 CalcBoundingBox(x1
, y1
);
281 CalcBoundingBox(x2
, y2
);
284 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
286 wxCHECK_RET( Ok(), "invalid dc" );
291 int xx
= XLOG2DEV (x
);
292 int yy
= YLOG2DEV (y
);
294 wxDisplaySize (&ww
, &hh
);
295 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
297 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
300 if (m_window
&& m_window
->GetBackingPixmap())
304 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
307 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
313 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
315 wxCHECK_RET( Ok(), "invalid dc" );
317 // FreeGetPixelCache();
319 int xx1
= XLOG2DEV (x1
);
320 int yy1
= YLOG2DEV (y1
);
321 int xx2
= XLOG2DEV (x2
);
322 int yy2
= YLOG2DEV (y2
);
323 int xxc
= XLOG2DEV (xc
);
324 int yyc
= YLOG2DEV (yc
);
325 int xxc_2
= XLOG2DEV_2 (xc
);
326 int yyc_2
= YLOG2DEV_2 (yc
);
328 wxCoord dx
= xx1
- xxc
;
329 wxCoord dy
= yy1
- yyc
;
330 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
331 wxCoord r
= (wxCoord
) radius
;
333 double radius1
, radius2
;
335 if (xx1
== xx2
&& yy1
== yy2
)
340 else if (radius
== 0.0)
341 radius1
= radius2
= 0.0;
350 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
358 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
362 int alpha1
= (int) radius1
;
363 int alpha2
= (int) (radius2
- radius1
);
366 while (alpha2
> 360 * 64)
369 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
372 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
373 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
375 if (m_window
&& m_window
->GetBackingPixmap())
376 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
377 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
381 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
385 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
386 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
388 if (m_window
&& m_window
->GetBackingPixmap())
389 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
390 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
392 CalcBoundingBox (x1
, y1
);
393 CalcBoundingBox (x2
, y2
);
396 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
398 wxCHECK_RET( Ok(), "invalid dc" );
404 wd
= XLOG2DEVREL(width
);
405 hd
= YLOG2DEVREL(height
);
407 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
408 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
409 int start
= int(sa
*64);
410 int end
= int(ea
*64);
411 if (start
<0) start
+=360*64;
412 if (end
<0) end
+=360*64;
413 if (end
>start
) end
-=start
;
414 else end
+=360*64-start
;
416 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
418 m_autoSetting
= TRUE
; // must be reset
421 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
423 if (m_window
&& m_window
->GetBackingPixmap())
424 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
425 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
428 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
432 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
433 if (m_window
&& m_window
->GetBackingPixmap())
434 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
435 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
437 CalcBoundingBox (x
, y
);
438 CalcBoundingBox (x
+ width
, y
+ height
);
441 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
443 wxCHECK_RET( Ok(), "invalid dc" );
445 // FreeGetPixelCache();
447 if (m_pen
.Ok() && m_autoSetting
)
450 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
451 if (m_window
&& m_window
->GetBackingPixmap())
452 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
454 CalcBoundingBox (x
, y
);
457 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
459 wxCHECK_RET( Ok(), "invalid dc" );
461 // FreeGetPixelCache();
463 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
468 XPoint
*xpoints
= new XPoint
[n
];
471 for (i
= 0; i
< n
; i
++)
473 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
474 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
476 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
478 if (m_window
&& m_window
->GetBackingPixmap())
480 for (i
= 0; i
< n
; i
++)
482 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
483 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
485 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
491 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
492 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
494 wxCHECK_RET( Ok(), "invalid dc" );
496 // FreeGetPixelCache();
498 XPoint
*xpoints1
= new XPoint
[n
+ 1];
499 XPoint
*xpoints2
= new XPoint
[n
+ 1];
501 for (i
= 0; i
< n
; i
++)
503 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
504 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
505 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
506 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
507 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
510 // Close figure for XDrawLines (not needed for XFillPolygon)
511 xpoints1
[i
].x
= xpoints1
[0].x
;
512 xpoints1
[i
].y
= xpoints1
[0].y
;
513 xpoints2
[i
].x
= xpoints2
[0].x
;
514 xpoints2
[i
].y
= xpoints2
[0].y
;
516 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
519 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
520 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
521 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
522 if (m_window
&& m_window
->GetBackingPixmap())
524 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
525 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
526 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
527 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
531 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
535 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
537 if (m_window
&& m_window
->GetBackingPixmap())
538 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
545 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
547 wxCHECK_RET( Ok(), "invalid dc" );
549 // FreeGetPixelCache();
551 int xd
, yd
, wfd
, hfd
, wd
, hd
;
555 wfd
= XLOG2DEVREL(width
);
557 hfd
= YLOG2DEVREL(height
);
560 if (wfd
== 0 || hfd
== 0) return;
561 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
562 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
564 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
567 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
569 if (m_window
&& m_window
->GetBackingPixmap())
570 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
571 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
575 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
579 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
581 if (m_window
&& m_window
->GetBackingPixmap())
582 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
583 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
586 CalcBoundingBox (x
, y
);
587 CalcBoundingBox (x
+ width
, y
+ height
);
590 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
592 wxCHECK_RET( Ok(), "invalid dc" );
594 // FreeGetPixelCache();
596 // If radius is negative, it's a proportion of the smaller dimension.
598 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
600 int xd
= XLOG2DEV (x
);
601 int yd
= YLOG2DEV (y
);
602 int rd
= XLOG2DEVREL ((long) radius
);
603 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
604 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
609 // If radius is zero use DrawRectangle() instead to avoid
610 // X drawing errors with small radii
613 DrawRectangle( x
, y
, width
, height
);
617 // Draw nothing if transformed w or h is 0
618 if (wd
== 0 || hd
== 0) return;
620 // CMB: adjust size if outline is drawn otherwise the result is
621 // 1 pixel too wide and high
622 if (m_pen
.GetStyle() != wxTRANSPARENT
)
628 // CMB: ensure dd is not larger than rectangle otherwise we
629 // get an hour glass shape
630 if (rw_d
> wd
) rw_d
= wd
;
631 if (rw_d
> hd
) rw_d
= hd
;
634 // For backing pixmap
635 int xd2
= XLOG2DEV_2 (x
);
636 int yd2
= YLOG2DEV_2 (y
);
637 int rd2
= XLOG2DEVREL ((long) radius
);
638 int wd2
= XLOG2DEVREL (width
) ;
639 int hd2
= YLOG2DEVREL (height
) ;
644 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
648 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
650 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
653 // Arcs start from 3 o'clock, positive angles anticlockwise
655 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
656 rw_d
, rh_d
, 90 * 64, 90 * 64);
658 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
659 // rw_d, rh_d, 0, 90 * 64);
660 rw_d
, rh_d
, 0, 91 * 64);
662 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
664 // rw_d, rh_d, 270 * 64, 90 * 64);
665 rw_d
, rh_d
, 269 * 64, 92 * 64);
667 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
668 rw_d
, rh_d
, 180 * 64, 90 * 64);
670 if (m_window
&& m_window
->GetBackingPixmap())
672 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
673 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
674 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
675 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
677 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
678 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
679 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
680 xd2
+ wd2
- rw_d2
, yd2
,
681 // rw_d2, rh_d2, 0, 90 * 64);
682 rw_d2
, rh_d2
, 0, 91 * 64);
683 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
686 // rw_d2, rh_d2, 270 * 64, 90 * 64);
687 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
688 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
689 xd2
, yd2
+ hd2
- rh_d2
,
690 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
694 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
697 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
698 xd
+ wd
- rd
+ 1, yd
);
699 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
700 xd
+ wd
- rd
, yd
+ hd
);
702 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
704 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
705 xd
+ wd
, yd
+ hd
- rd
+ 1);
706 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
707 rw_d
, rh_d
, 90 * 64, 90 * 64);
708 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
709 // rw_d, rh_d, 0, 90 * 64);
710 rw_d
, rh_d
, 0, 91 * 64);
711 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
713 rw_d
, rh_d
, 269 * 64, 92 * 64);
714 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
715 rw_d
, rh_d
, 180 * 64, 90 * 64);
717 if (m_window
&& m_window
->GetBackingPixmap())
719 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
721 xd2
+ wd2
- rd2
+ 1, yd2
);
722 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
723 xd2
+ rd2
, yd2
+ hd2
,
724 xd2
+ wd2
- rd2
, yd2
+ hd2
);
726 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
728 xd2
, yd2
+ hd2
- rd2
);
729 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
730 xd2
+ wd2
, yd2
+ rd2
,
731 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
732 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
734 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
735 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
736 xd2
+ wd2
- rw_d2
, yd2
,
737 // rw_d2, rh_d2, 0, 90 * 64);
738 rw_d2
, rh_d2
, 0, 91 * 64);
739 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
742 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
743 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
744 xd2
, yd2
+ hd2
- rh_d2
,
745 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
748 CalcBoundingBox (x
, y
);
749 CalcBoundingBox (x
+ width
, y
+ height
);
754 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
756 wxCHECK_RET( Ok(), "invalid dc" );
758 // Check for negative width and height
771 // FreeGetPixelCache();
773 static const int angle
= 23040;
779 wd
= XLOG2DEVREL(width
) ;
780 hd
= YLOG2DEVREL(height
) ;
782 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
785 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
786 if (m_window
&& m_window
->GetBackingPixmap())
787 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
788 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
789 XLOG2DEVREL (width
) - WX_GC_CF
,
790 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
793 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
797 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
798 if (m_window
&& m_window
->GetBackingPixmap())
799 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
800 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
801 XLOG2DEVREL (width
) - WX_GC_CF
,
802 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
804 CalcBoundingBox (x
, y
);
805 CalcBoundingBox (x
+ width
, y
+ height
);
809 bool wxWindowDC::CanDrawBitmap() const
811 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
817 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
819 // FreeGetPixelCache();
821 // Be sure that foreground pixels (1) of
822 // the Icon will be painted with pen colour. [m_pen.SetColour()]
823 // Background pixels (0) will be painted with
824 // last selected background color. [::SetBackground]
825 if (m_pen
.Ok() && m_autoSetting
)
829 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
830 width
= icon
.GetWidth();
831 height
= icon
.GetHeight();
832 if (icon
.GetDisplay() == m_display
)
834 if (icon
.GetDepth() <= 1)
836 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
838 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
842 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
844 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
848 if (m_window
&& m_window
->GetBackingPixmap())
850 if (icon
.GetDepth() <= 1)
852 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
853 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
857 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
859 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
862 } else { /* Remote copy (different (Display*) m_displays) */
863 XImage
*cache
= NULL
;
864 if (m_window
&& m_window
->GetBackingPixmap())
865 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
866 (GC
) m_gcBacking
, 0, 0, width
, height
,
867 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
868 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
870 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
872 CalcBoundingBox (x
, y
);
876 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
877 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
878 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
879 wxCoord xsrcMask
, wxCoord ysrcMask
)
881 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
883 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
885 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
887 // FreeGetPixelCache();
889 // Be sure that foreground pixels (1) of the Icon will be painted with pen
890 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
891 // last selected background color. [::SetBackground]
892 if (m_pen
.Ok() && m_autoSetting
)
895 // Do bitmap scaling if necessary
897 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
898 Pixmap sourcePixmap
= (Pixmap
) NULL
;
899 double scaleX
, scaleY
;
900 GetUserScale(& scaleX
, & scaleY
);
902 /* TODO: use the mask origin when drawing transparently */
903 if (xsrcMask
== -1 && ysrcMask
== -1)
905 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
908 // Sorry, can't scale masks just yet
909 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
911 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
912 wxBitmap
& bitmap
= memDC
->GetBitmap();
914 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
916 wxImage
image(bitmap
);
919 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
923 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
924 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
926 image
= image
.Scale(scaledW
, scaledH
);
927 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
928 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
932 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
934 if (m_pixmap
&& sourcePixmap
)
937 int orig
= m_logicalFunction
;
939 SetLogicalFunction (rop
);
941 if (m_display
!= sourceDC
->m_display
)
943 XImage
*cache
= NULL
;
945 if (m_window
&& m_window
->GetBackingPixmap())
946 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
947 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
949 source
->LogicalToDeviceX (xsrc
),
950 source
->LogicalToDeviceY (ysrc
),
951 source
->LogicalToDeviceXRel(width
),
952 source
->LogicalToDeviceYRel(height
),
953 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
956 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
958 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
959 wxBitmap
& sel
= memDC
->GetBitmap();
960 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
962 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
963 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
967 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
968 source
->LogicalToDeviceX (xsrc
),
969 source
->LogicalToDeviceY (ysrc
),
970 source
->LogicalToDeviceXRel(width
),
971 source
->LogicalToDeviceYRel(height
),
972 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
977 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
978 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
983 if (m_window
&& m_window
->GetBackingPixmap())
985 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
986 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
988 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
989 source
->LogicalToDeviceX (xsrc
),
990 source
->LogicalToDeviceY (ysrc
),
991 source
->LogicalToDeviceXRel(width
),
992 source
->LogicalToDeviceYRel(height
),
993 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
997 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
998 source
->LogicalToDeviceX (xsrc
),
999 source
->LogicalToDeviceY (ysrc
),
1000 source
->LogicalToDeviceXRel(width
),
1001 source
->LogicalToDeviceYRel(height
),
1002 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
1005 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1007 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1008 wxBitmap
& sel
= memDC
->GetBitmap();
1009 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1011 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1012 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1016 // Check if we're copying from a mono bitmap
1017 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1018 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1020 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1021 source
->LogicalToDeviceX (xsrc
),
1022 source
->LogicalToDeviceY (ysrc
),
1023 source
->LogicalToDeviceXRel(width
),
1024 source
->LogicalToDeviceYRel(height
),
1025 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1029 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1030 source
->LogicalToDeviceX (xsrc
),
1031 source
->LogicalToDeviceY (ysrc
),
1032 source
->LogicalToDeviceXRel(width
),
1033 source
->LogicalToDeviceYRel(height
),
1034 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1039 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1040 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1043 } /* Remote/local (Display*) m_display */
1044 CalcBoundingBox (xdest
, ydest
);
1045 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1047 SetLogicalFunction(orig
);
1049 if (scaledBitmap
) delete scaledBitmap
;
1053 if (scaledBitmap
) delete scaledBitmap
;
1058 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1060 wxCHECK_RET( Ok(), "invalid dc" );
1062 // Since X draws from the baseline of the text, must add the text height
1068 slen
= strlen(text
);
1072 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1073 int direction
, descent
;
1074 XCharStruct overall_return
;
1077 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1078 &ascent
, &descent
, &overall_return
);
1081 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1082 &ascent
, &descent
, &overall_return
);
1084 cx
= overall_return
.width
;
1085 cy
= ascent
+ descent
;
1088 // First draw a rectangle representing the text background, if a text
1089 // background is specified
1090 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1092 wxColour oldPenColour
= m_currentColour
;
1093 m_currentColour
= m_textBackgroundColour
;
1094 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1095 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1096 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1097 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1099 // This separation of the big && test required for gcc2.7/HP UX 9.02
1100 // or pixel value can be corrupted!
1101 sameColour
= (sameColour
&&
1102 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1104 if (!sameColour
|| !GetOptimization())
1106 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1107 m_currentColour
= m_textBackgroundColour
;
1109 // Set the GC to the required colour
1112 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1113 if (m_window
&& m_window
->GetBackingPixmap())
1114 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1118 m_textBackgroundColour
= oldPenColour
;
1120 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1121 if (m_window
&& m_window
->GetBackingPixmap())
1122 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1123 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1126 // Now set the text foreground and draw the text
1127 if (m_textForegroundColour
.Ok ())
1129 wxColour oldPenColour
= m_currentColour
;
1130 m_currentColour
= m_textForegroundColour
;
1131 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1132 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1133 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1134 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1135 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1137 if (!sameColour
|| !GetOptimization())
1140 if (!m_colour
) // Mono display
1142 // Unless foreground is really white, draw it in black
1143 unsigned char red
= m_textForegroundColour
.Red ();
1144 unsigned char blue
= m_textForegroundColour
.Blue ();
1145 unsigned char green
= m_textForegroundColour
.Green ();
1146 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1147 && green
== (unsigned char) 255)
1149 m_currentColour
= *wxWHITE
;
1150 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1151 m_currentColour
.SetPixel(pixel
);
1152 m_textForegroundColour
.SetPixel(pixel
);
1156 m_currentColour
= *wxBLACK
;
1157 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1158 m_currentColour
.SetPixel(pixel
);
1159 m_textForegroundColour
.SetPixel(pixel
);
1164 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1165 m_currentColour
.SetPixel(pixel
);
1168 // Set the GC to the required colour
1171 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1172 if (m_window
&& m_window
->GetBackingPixmap())
1173 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1177 m_textForegroundColour
= oldPenColour
;
1180 // We need to add the ascent, not the whole height, since X draws at the
1181 // point above the descender.
1184 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1185 (XChar2b
*)(char*) (const char*) text
, slen
);
1188 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1190 if (m_window
&& m_window
->GetBackingPixmap()) {
1193 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1194 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1195 (XChar2b
*)(char*) (const char*) text
, slen
);
1198 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1199 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1203 GetTextExtent (text
, &w
, &h
);
1204 CalcBoundingBox (x
+ w
, y
+ h
);
1205 CalcBoundingBox (x
, y
);
1208 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1212 DrawText(text
, x
, y
);
1216 wxCHECK_RET( Ok(), "invalid dc" );
1218 // Since X draws from the baseline of the text, must add the text height
1224 slen
= strlen(text
);
1228 // Calculate text extent.
1229 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1230 int direction
, descent
;
1231 XCharStruct overall_return
;
1234 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1235 &ascent
, &descent
, &overall_return
);
1238 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1239 &ascent
, &descent
, &overall_return
);
1241 cx
= overall_return
.width
;
1242 cy
= ascent
+ descent
;
1245 wxBitmap
src(cx
, cy
);
1247 dc
.SelectObject(src
);
1248 dc
.SetFont(GetFont());
1249 dc
.SetBackground(*wxWHITE_BRUSH
);
1250 dc
.SetBrush(*wxBLACK_BRUSH
);
1252 dc
.DrawText(text
, 0, 0);
1253 dc
.SetFont(wxNullFont
);
1255 // Calculate the size of the rotated bounding box.
1256 double dx
= cos(angle
/ 180.0 * M_PI
);
1257 double dy
= sin(angle
/ 180.0 * M_PI
);
1258 double x4
= -cy
* dy
;
1259 double y4
= cy
* dx
;
1260 double x3
= cx
* dx
;
1261 double y3
= cx
* dy
;
1262 double x2
= x3
+ x4
;
1263 double y2
= y3
+ y4
;
1267 // Create image from the source bitmap after writing the text into it.
1270 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1271 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1272 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1273 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1275 // This rotates counterclockwise around the top left corner.
1276 for (int rx
= minx
; rx
< maxx
; rx
++)
1278 for (int ry
= miny
; ry
< maxy
; ry
++)
1280 // transform dest coords to source coords
1281 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1282 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1283 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1285 // draw black pixels, ignore white ones (i.e. transparent b/g)
1286 if (image
.GetRed(sx
, sy
) == 0)
1288 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1293 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1300 // First draw a rectangle representing the text background, if a text
1301 // background is specified
1302 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1304 wxColour oldPenColour
= m_currentColour
;
1305 m_currentColour
= m_textBackgroundColour
;
1306 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1307 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1308 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1309 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1311 // This separation of the big && test required for gcc2.7/HP UX 9.02
1312 // or pixel value can be corrupted!
1313 sameColour
= (sameColour
&&
1314 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1316 if (!sameColour
|| !GetOptimization())
1318 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1319 m_currentColour
= m_textBackgroundColour
;
1321 // Set the GC to the required colour
1324 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1325 if (m_window
&& m_window
->GetBackingPixmap())
1326 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1330 m_textBackgroundColour
= oldPenColour
;
1332 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1333 if (m_window
&& m_window
->GetBackingPixmap())
1334 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1335 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1340 // XXX use pixmap size
1341 GetTextExtent (text
, &w
, &h
);
1342 CalcBoundingBox (x
+ w
, y
+ h
);
1343 CalcBoundingBox (x
, y
);
1346 bool wxWindowDC::CanGetTextExtent() const
1351 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1352 wxCoord
*descent
, wxCoord
*externalLeading
,
1353 wxFont
*font
) const
1355 wxCHECK_RET( Ok(), "invalid dc" );
1357 wxFont
* theFont
= font
;
1359 theFont
= (wxFont
*)&m_font
; // const_cast
1363 // TODO: this should be an error log function
1364 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1366 if (width
) *width
= -1;
1367 if (height
) *height
= -1;
1371 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1373 int direction
, ascent
, descent2
;
1374 XCharStruct overall
;
1379 slen
= str16len(string
);
1382 slen
= strlen(string
);
1386 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1387 &ascent
, &descent2
, &overall
);
1390 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1391 &ascent
, &descent2
, &overall
);
1393 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1394 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1396 *descent
= descent2
;
1397 if (externalLeading
)
1398 *externalLeading
= 0;
1401 wxCoord
wxWindowDC::GetCharWidth() const
1403 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1404 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1406 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1408 int direction
, ascent
, descent
;
1409 XCharStruct overall
;
1410 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1411 &descent
, &overall
);
1412 return XDEV2LOGREL(overall
.width
);
1415 wxCoord
wxWindowDC::GetCharHeight() const
1417 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1418 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1420 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1422 int direction
, ascent
, descent
;
1423 XCharStruct overall
;
1424 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1425 &descent
, &overall
);
1426 // return XDEV2LOGREL(overall.ascent + overall.descent);
1427 return XDEV2LOGREL(ascent
+ descent
);
1430 void wxWindowDC::Clear()
1432 wxCHECK_RET( Ok(), "invalid dc" );
1437 m_window
->GetSize(&w
, &h
);
1439 if (m_window
&& m_window
->GetBackingPixmap())
1441 w
= m_window
->GetPixmapWidth();
1442 h
= m_window
->GetPixmapHeight();
1447 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1449 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1450 w
= memDC
->GetBitmap().GetWidth();
1451 h
= memDC
->GetBitmap().GetHeight();
1457 wxBrush saveBrush
= m_brush
;
1458 SetBrush (m_backgroundBrush
);
1460 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1462 if (m_window
&& m_window
->GetBackingPixmap())
1463 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1465 m_brush
= saveBrush
;
1468 void wxWindowDC::Clear(const wxRect
& rect
)
1470 wxCHECK_RET( Ok(), "invalid dc" );
1472 int x
= rect
.x
; int y
= rect
.y
;
1473 int w
= rect
.width
; int h
= rect
.height
;
1475 wxBrush saveBrush
= m_brush
;
1476 SetBrush (m_backgroundBrush
);
1478 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1480 if (m_window
&& m_window
->GetBackingPixmap())
1481 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1483 m_brush
= saveBrush
;
1486 void wxWindowDC::SetFont( const wxFont
&font
)
1488 wxCHECK_RET( Ok(), "invalid dc" );
1494 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1496 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1498 if (m_window
&& m_window
->GetBackingPixmap())
1499 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1504 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1506 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1507 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1509 if (m_window
&& m_window
->GetBackingPixmap())
1510 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1513 void wxWindowDC::SetPen( const wxPen
&pen
)
1515 wxCHECK_RET( Ok(), "invalid dc" );
1521 wxBitmap oldStipple
= m_currentStipple
;
1522 int oldStyle
= m_currentStyle
;
1523 int oldFill
= m_currentFill
;
1524 int old_pen_width
= m_currentPenWidth
;
1525 int old_pen_join
= m_currentPenJoin
;
1526 int old_pen_cap
= m_currentPenCap
;
1527 int old_pen_nb_dash
= m_currentPenDashCount
;
1528 wxMOTIFDash
*old_pen_dash
= m_currentPenDash
;
1530 wxColour oldPenColour
= m_currentColour
;
1531 m_currentColour
= m_pen
.GetColour ();
1532 m_currentStyle
= m_pen
.GetStyle ();
1533 m_currentFill
= m_pen
.GetStyle (); // TODO?
1534 m_currentPenWidth
= m_pen
.GetWidth ();
1535 m_currentPenJoin
= m_pen
.GetJoin ();
1536 m_currentPenCap
= m_pen
.GetCap ();
1537 m_currentPenDashCount
= m_pen
.GetDashCount();
1538 m_currentPenDash
= (wxMOTIFDash
*)m_pen
.GetDash();
1540 if (m_currentStyle
== wxSTIPPLE
)
1541 m_currentStipple
= * m_pen
.GetStipple ();
1543 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1544 oldFill
== m_currentFill
&&
1545 old_pen_join
== m_currentPenJoin
&&
1546 old_pen_cap
== m_currentPenCap
&&
1547 old_pen_nb_dash
== m_currentPenDashCount
&&
1548 old_pen_dash
== m_currentPenDash
&&
1549 old_pen_width
== m_currentPenWidth
);
1551 bool sameColour
= (oldPenColour
.Ok () &&
1552 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1553 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1554 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1555 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1557 if (!sameStyle
|| !GetOptimization())
1559 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1560 if (scaled_width
< 0)
1566 static const wxMOTIFDash dotted
[] = {2, 5};
1567 static const wxMOTIFDash short_dashed
[] = {4, 4};
1568 static const wxMOTIFDash long_dashed
[] = {4, 8};
1569 static const wxMOTIFDash dotted_dashed
[] = {6, 6, 2, 6};
1571 // We express dash pattern in pen width unit, so we are
1572 // independent of zoom factor and so on...
1574 const wxMOTIFDash
*req_dash
;
1576 switch (m_pen
.GetStyle ())
1579 req_nb_dash
= m_currentPenDashCount
;
1580 req_dash
= m_currentPenDash
;
1581 style
= LineOnOffDash
;
1586 style
= LineOnOffDash
;
1590 req_dash
= short_dashed
;
1591 style
= LineOnOffDash
;
1595 req_dash
= long_dashed
;
1596 style
= LineOnOffDash
;
1600 req_dash
= dotted_dashed
;
1601 style
= LineOnOffDash
;
1608 req_dash
= (wxMOTIFDash
*)NULL
;
1612 if (req_dash
&& req_nb_dash
)
1614 wxMOTIFDash
*real_req_dash
= new wxMOTIFDash
[req_nb_dash
];
1617 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1618 for (int i
= 0; i
< req_nb_dash
; i
++)
1619 real_req_dash
[i
] = req_dash
[i
] * factor
;
1620 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1622 if (m_window
&& m_window
->GetBackingPixmap())
1623 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1624 delete[]real_req_dash
;
1628 // No Memory. We use non-scaled dash pattern...
1629 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1631 if (m_window
&& m_window
->GetBackingPixmap())
1632 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1636 switch (m_pen
.GetCap ())
1638 case wxCAP_PROJECTING
:
1639 cap
= CapProjecting
;
1646 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1650 switch (m_pen
.GetJoin ())
1664 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1666 if (m_window
&& m_window
->GetBackingPixmap())
1667 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1670 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1674 oldStipple
= wxNullBitmap
; // For later reset!!
1676 switch (m_currentFill
)
1678 case wxBDIAGONAL_HATCH
:
1679 if (bdiag
== (Pixmap
) 0)
1680 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1681 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1682 bdiag_bits
, bdiag_width
, bdiag_height
);
1685 case wxFDIAGONAL_HATCH
:
1686 if (fdiag
== (Pixmap
) 0)
1687 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1688 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1689 fdiag_bits
, fdiag_width
, fdiag_height
);
1693 if (cross
== (Pixmap
) 0)
1694 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1695 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1696 cross_bits
, cross_width
, cross_height
);
1699 case wxHORIZONTAL_HATCH
:
1700 if (horiz
== (Pixmap
) 0)
1701 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1702 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1703 horiz_bits
, horiz_width
, horiz_height
);
1706 case wxVERTICAL_HATCH
:
1707 if (verti
== (Pixmap
) 0)
1708 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1709 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1710 verti_bits
, verti_width
, verti_height
);
1713 case wxCROSSDIAG_HATCH
:
1715 if (cdiag
== (Pixmap
) 0)
1716 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1717 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1718 cdiag_bits
, cdiag_width
, cdiag_height
);
1722 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1724 if (m_window
&& m_window
->GetBackingPixmap())
1725 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1727 else if (m_currentStipple
.Ok()
1728 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1730 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1732 if (m_window
&& m_window
->GetBackingPixmap())
1733 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1736 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1740 if (m_currentFill
== wxSTIPPLE
)
1741 fill_style
= FillStippled
;
1742 else if (IS_HATCH (m_currentFill
))
1743 fill_style
= FillStippled
;
1745 fill_style
= FillSolid
;
1746 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1747 if (m_window
&& m_window
->GetBackingPixmap())
1748 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1751 // must test m_logicalFunction, because it involves background!
1752 if (!sameColour
|| !GetOptimization()
1753 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1756 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1757 pixel
= m_backgroundPixel
;
1760 unsigned char red
= m_pen
.GetColour ().Red ();
1761 unsigned char blue
= m_pen
.GetColour ().Blue ();
1762 unsigned char green
= m_pen
.GetColour ().Green ();
1763 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1764 && green
== (unsigned char) 255)
1766 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1767 m_currentColour
= *wxWHITE
;
1768 m_pen
.GetColour().SetPixel(pixel
);
1769 m_currentColour
.SetPixel(pixel
);
1773 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1774 m_currentColour
= *wxBLACK
;
1775 m_pen
.GetColour().SetPixel(pixel
);
1780 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1781 m_currentColour
.SetPixel(pixel
);
1784 // Finally, set the GC to the required colour
1787 if (m_logicalFunction
== wxXOR
)
1790 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1791 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1792 if (m_window
&& m_window
->GetBackingPixmap())
1793 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1797 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1798 if (m_window
&& m_window
->GetBackingPixmap())
1799 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1804 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1809 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1811 wxCHECK_RET( Ok(), "invalid dc" );
1815 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1818 int oldFill
= m_currentFill
;
1819 wxBitmap oldStipple
= m_currentStipple
;
1821 m_autoSetting
|= 0x1;
1823 m_currentFill
= m_brush
.GetStyle ();
1824 if (m_currentFill
== wxSTIPPLE
)
1825 m_currentStipple
= * m_brush
.GetStipple ();
1827 wxColour
oldBrushColour(m_currentColour
);
1828 m_currentColour
= m_brush
.GetColour ();
1830 bool sameColour
= (oldBrushColour
.Ok () &&
1831 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1832 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1833 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1834 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1836 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1838 switch (brush
.GetStyle ())
1842 case wxBDIAGONAL_HATCH
:
1843 case wxCROSSDIAG_HATCH
:
1844 case wxFDIAGONAL_HATCH
:
1846 case wxHORIZONTAL_HATCH
:
1847 case wxVERTICAL_HATCH
:
1850 // Chris Breeze 23/07/97: use background mode to determine whether
1851 // fill style should be solid or transparent
1852 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1853 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1854 if (m_window
&& m_window
->GetBackingPixmap())
1855 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1860 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1861 if (m_window
&& m_window
->GetBackingPixmap())
1862 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1866 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1870 switch (m_currentFill
)
1872 case wxBDIAGONAL_HATCH
:
1873 if (bdiag
== (Pixmap
) 0)
1874 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1875 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1876 bdiag_bits
, bdiag_width
, bdiag_height
);
1879 case wxFDIAGONAL_HATCH
:
1880 if (fdiag
== (Pixmap
) 0)
1881 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1882 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1883 fdiag_bits
, fdiag_width
, fdiag_height
);
1887 if (cross
== (Pixmap
) 0)
1888 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1889 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1890 cross_bits
, cross_width
, cross_height
);
1893 case wxHORIZONTAL_HATCH
:
1894 if (horiz
== (Pixmap
) 0)
1895 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1896 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1897 horiz_bits
, horiz_width
, horiz_height
);
1900 case wxVERTICAL_HATCH
:
1901 if (verti
== (Pixmap
) 0)
1902 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1903 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1904 verti_bits
, verti_width
, verti_height
);
1907 case wxCROSSDIAG_HATCH
:
1909 if (cdiag
== (Pixmap
) 0)
1910 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1911 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1912 cdiag_bits
, cdiag_width
, cdiag_height
);
1916 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1918 if (m_window
&& m_window
->GetBackingPixmap())
1919 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1921 // X can forget the stipple value when resizing a window (apparently)
1922 // so always set the stipple.
1923 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1925 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1926 if (m_window
&& m_window
->GetBackingPixmap())
1927 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1930 // must test m_logicalFunction, because it involves background!
1931 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1936 // Policy - on a monochrome screen, all brushes are white,
1937 // except when they're REALLY black!!!
1938 unsigned char red
= m_brush
.GetColour ().Red ();
1939 unsigned char blue
= m_brush
.GetColour ().Blue ();
1940 unsigned char green
= m_brush
.GetColour ().Green ();
1942 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1943 && green
== (unsigned char) 0)
1945 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1946 m_currentColour
= *wxBLACK
;
1947 m_brush
.GetColour().SetPixel(pixel
);
1948 m_currentColour
.SetPixel(pixel
);
1952 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1953 m_currentColour
= *wxWHITE
;
1954 m_brush
.GetColour().SetPixel(pixel
);
1955 m_currentColour
.SetPixel(pixel
);
1958 // N.B. comment out the above line and uncomment the following lines
1959 // if you want non-white colours to be black on a monochrome display.
1961 if (red == (unsigned char )255 && blue == (unsigned char)255
1962 && green == (unsigned char)255)
1963 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1965 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1968 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1970 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1971 m_currentColour
.SetPixel(pixel
);
1975 // Finally, set the GC to the required colour
1976 if (m_logicalFunction
== wxXOR
)
1979 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1980 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1981 if (m_window
&& m_window
->GetBackingPixmap())
1982 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1986 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1987 if (m_window
&& m_window
->GetBackingPixmap())
1988 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1993 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1996 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1998 wxCHECK_RET( Ok(), "invalid dc" );
2000 m_backgroundBrush
= brush
;
2002 if (!m_backgroundBrush
.Ok())
2005 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
2007 // New behaviour, 10/2/99: setting the background brush of a DC
2008 // doesn't affect the window background colour.
2010 // XSetWindowBackground doesn't work for non-Window pixmaps
2011 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2012 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2015 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2016 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2017 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2018 if (m_window
&& m_window
->GetBackingPixmap())
2019 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2022 void wxWindowDC::SetLogicalFunction( int function
)
2024 wxCHECK_RET( Ok(), "invalid dc" );
2029 if (m_logicalFunction
== function
)
2035 x_function
= GXclear
;
2041 x_function
= GXinvert
;
2044 x_function
= GXorReverse
;
2047 x_function
= GXandReverse
;
2056 x_function
= GXandInverted
;
2059 x_function
= GXnoop
;
2065 x_function
= GXequiv
;
2068 x_function
= GXcopyInverted
;
2071 x_function
= GXorInverted
;
2074 x_function
= GXnand
;
2081 x_function
= GXcopy
;
2085 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2086 if (m_window
&& m_window
->GetBackingPixmap())
2087 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2089 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2090 /* MATTHEW: [9] Need to redo pen simply */
2091 m_autoSetting
|= 0x2;
2093 m_logicalFunction
= function
;
2097 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2099 wxCHECK_RET( Ok(), "invalid dc" );
2101 if (m_textForegroundColour
== col
)
2104 m_textForegroundColour
= col
;
2108 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2110 wxCHECK_RET( Ok(), "invalid dc" );
2112 if (m_textBackgroundColour
== col
)
2115 m_textBackgroundColour
= col
;
2116 if (!m_textBackgroundColour
.Ok())
2120 void wxWindowDC::SetBackgroundMode( int mode
)
2122 m_backgroundMode
= mode
;
2125 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2130 /* Use GetXColormap */
2131 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2132 (Colormap
) palette
.GetXColormap());
2134 /* Use wxGetMainColormap */
2135 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2136 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2141 void wxWindowDC::SetDCClipping()
2143 // m_userRegion is the region set by calling SetClippingRegion
2145 if (m_currentRegion
)
2146 XDestroyRegion ((Region
) m_currentRegion
);
2148 // We need to take into account
2149 // clipping imposed on a window by a repaint.
2150 // We'll combine it with the user region. But for now,
2151 // just use the currently-defined user clipping region.
2152 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2153 m_currentRegion
= (WXRegion
) XCreateRegion ();
2155 m_currentRegion
= (WXRegion
) NULL
;
2157 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2158 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2159 else if (m_userRegion
)
2160 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2161 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2162 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2163 (Region
) m_currentRegion
);
2165 if (m_currentRegion
)
2167 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2171 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2176 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2178 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2181 XDestroyRegion ((Region
) m_userRegion
);
2182 m_userRegion
= (WXRegion
) XCreateRegion ();
2186 r
.width
= XLOG2DEVREL(width
);
2187 r
.height
= YLOG2DEVREL(height
);
2188 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2192 // Needs to work differently for Pixmap: without this,
2193 // there's a nasty (Display*) m_display bug. 8/12/94
2194 if (m_window
&& m_window
->GetBackingPixmap())
2196 XRectangle rects
[1];
2197 rects
[0].x
= XLOG2DEV_2(x
);
2198 rects
[0].y
= YLOG2DEV_2(y
);
2199 rects
[0].width
= XLOG2DEVREL(width
);
2200 rects
[0].height
= YLOG2DEVREL(height
);
2201 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2205 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2207 wxRect box
= region
.GetBox();
2209 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2212 XDestroyRegion ((Region
) m_userRegion
);
2213 m_userRegion
= (WXRegion
) XCreateRegion ();
2215 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2219 // Needs to work differently for Pixmap: without this,
2220 // there's a nasty (Display*) m_display bug. 8/12/94
2221 if (m_window
&& m_window
->GetBackingPixmap())
2223 XRectangle rects
[1];
2224 rects
[0].x
= XLOG2DEV_2(box
.x
);
2225 rects
[0].y
= YLOG2DEV_2(box
.y
);
2226 rects
[0].width
= XLOG2DEVREL(box
.width
);
2227 rects
[0].height
= YLOG2DEVREL(box
.height
);
2228 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2233 void wxWindowDC::DestroyClippingRegion()
2235 wxDC::DestroyClippingRegion();
2238 XDestroyRegion ((Region
) m_userRegion
);
2239 m_userRegion
= NULL
;
2244 gc_val
.clip_mask
= None
;
2245 if (m_window
&& m_window
->GetBackingPixmap())
2246 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2249 // Resolution in pixels per logical inch
2250 wxSize
wxWindowDC::GetPPI() const
2252 return wxSize(100, 100);
2255 int wxWindowDC::GetDepth() const
2264 // ----------------------------------------------------------------------------
2266 // ----------------------------------------------------------------------------
2268 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2270 wxRegion
* region
= NULL
;
2272 // Combine all the update rects into a region
2273 const wxRectList
& updateRects(win
->GetUpdateRects());
2274 if ( updateRects
.GetCount() != 0 )
2276 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2278 node
= node
->GetNext() )
2280 wxRect
* rect
= node
->GetData();
2283 region
= new wxRegion(*rect
);
2285 // TODO: is this correct? In SetDCClipping above,
2286 // XIntersectRegion is used to combine paint and user
2287 // regions. XIntersectRegion appears to work in that case...
2288 region
->Union(*rect
);
2294 win
->GetClientSize(&cw
, &ch
);
2295 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2298 win
->SetUpdateRegion(*region
);
2300 wxRegion
& theRegion(win
->GetUpdateRegion());
2301 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2303 // Set the clipping region. Any user-defined region will be combined with this
2304 // one in SetDCClipping.
2305 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2310 wxPaintDC::~wxPaintDC()
2312 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2314 m_window
->ClearUpdateRegion();
2317 // ----------------------------------------------------------------------------
2318 // private functions
2319 // ----------------------------------------------------------------------------
2322 Used when copying between drawables on different (Display*) m_displays. Not
2323 very fast, but better than giving up.
2326 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2327 Drawable src
, Drawable dest
,
2330 unsigned int w
, unsigned int h
,
2331 int destx
, int desty
,
2332 bool more
, XImage
**cache
)
2334 XImage
*image
, *destimage
;
2335 Colormap destcm
, srccm
;
2336 static const int CACHE_SIZE
= 256;
2339 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2340 int k
, cache_pos
, all_cache
;
2342 if (!cache
|| !*cache
)
2343 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2347 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2349 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2350 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2355 for (i
= 0; i
< w
; i
++)
2356 for (j
= 0; j
< h
; j
++) {
2357 unsigned long pixel
;
2360 pixel
= XGetPixel(image
, i
, j
);
2361 for (k
= cache_pos
; k
--; )
2362 if (cachesrc
[k
] == pixel
) {
2363 pixel
= cachedest
[k
];
2367 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2368 if (cachesrc
[k
] == pixel
) {
2369 pixel
= cachedest
[k
];
2373 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2374 XQueryColor(src_display
, srccm
, &xcol
);
2375 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2377 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2379 if (++cache_pos
>= CACHE_SIZE
) {
2385 XPutPixel(destimage
, i
, j
, pixel
);
2388 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2389 XDestroyImage(destimage
);
2394 XDestroyImage(image
);
2399 /* Helper function for 16-bit fonts */
2400 static int str16len(const char *s
)
2404 while (s
[0] && s
[1]) {