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
.ConvertToImage();
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
890 // foreground colour. [m_textForegroundColour] Background pixels (0)
891 // will be painted with backgound colour (m_textBackgroundColour)
892 // Using ::SetPen is horribly slow, so avoid doing it
893 int oldBackgroundPixel
= -1;
894 int oldForegroundPixel
= -1;
896 if (m_textBackgroundColour
.Ok())
898 oldBackgroundPixel
= m_backgroundPixel
;
899 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
901 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
902 if (m_window
&& m_window
->GetBackingPixmap())
903 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
906 if (m_textForegroundColour
.Ok())
908 oldForegroundPixel
= m_currentColour
.GetPixel();
910 if( m_textForegroundColour
.GetPixel() <= -1 )
911 CalculatePixel( m_textForegroundColour
,
912 m_textForegroundColour
, TRUE
);
914 int pixel
= m_textForegroundColour
.GetPixel();
916 SetForegroundPixelWithLogicalFunction(pixel
);
919 // Do bitmap scaling if necessary
921 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
922 Pixmap sourcePixmap
= (Pixmap
) NULL
;
923 double scaleX
, scaleY
;
924 GetUserScale(& scaleX
, & scaleY
);
927 /* TODO: use the mask origin when drawing transparently */
928 if (xsrcMask
== -1 && ysrcMask
== -1)
930 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
933 // Sorry, can't scale masks just yet
934 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
936 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
937 wxBitmap
& bitmap
= memDC
->GetBitmap();
939 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
941 wxImage image
= bitmap
.ConvertToImage();
944 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
948 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
949 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
951 image
= image
.Scale(scaledW
, scaledH
);
952 scaledBitmap
= new wxBitmap(image
);
953 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
957 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
959 if (m_pixmap
&& sourcePixmap
)
962 int orig
= m_logicalFunction
;
964 SetLogicalFunction (rop
);
966 if (m_display
!= sourceDC
->m_display
)
968 XImage
*cache
= NULL
;
970 if (m_window
&& m_window
->GetBackingPixmap())
971 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
972 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
974 source
->LogicalToDeviceX (xsrc
),
975 source
->LogicalToDeviceY (ysrc
),
976 source
->LogicalToDeviceXRel(width
),
977 source
->LogicalToDeviceYRel(height
),
978 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
981 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
983 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
984 wxBitmap
& sel
= memDC
->GetBitmap();
985 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
987 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
988 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
992 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
993 source
->LogicalToDeviceX (xsrc
),
994 source
->LogicalToDeviceY (ysrc
),
995 source
->LogicalToDeviceXRel(width
),
996 source
->LogicalToDeviceYRel(height
),
997 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
1002 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1003 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1007 { //XGCValues values;
1008 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
1010 if (m_window
&& m_window
->GetBackingPixmap())
1012 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
1013 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
1015 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1016 source
->LogicalToDeviceX (xsrc
),
1017 source
->LogicalToDeviceY (ysrc
),
1018 source
->LogicalToDeviceXRel(width
),
1019 source
->LogicalToDeviceYRel(height
),
1020 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
1024 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1025 source
->LogicalToDeviceX (xsrc
),
1026 source
->LogicalToDeviceY (ysrc
),
1027 source
->LogicalToDeviceXRel(width
),
1028 source
->LogicalToDeviceYRel(height
),
1029 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
1032 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1034 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1035 wxBitmap
& sel
= memDC
->GetBitmap();
1036 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1038 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1039 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1043 // Check if we're copying from a mono bitmap
1044 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1045 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1047 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1048 source
->LogicalToDeviceX (xsrc
),
1049 source
->LogicalToDeviceY (ysrc
),
1050 source
->LogicalToDeviceXRel(width
),
1051 source
->LogicalToDeviceYRel(height
),
1052 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1056 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1057 source
->LogicalToDeviceX (xsrc
),
1058 source
->LogicalToDeviceY (ysrc
),
1059 source
->LogicalToDeviceXRel(width
),
1060 source
->LogicalToDeviceYRel(height
),
1061 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1066 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1067 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1070 } /* Remote/local (Display*) m_display */
1071 CalcBoundingBox (xdest
, ydest
);
1072 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1074 SetLogicalFunction(orig
);
1078 if (scaledBitmap
) delete scaledBitmap
;
1080 if (oldBackgroundPixel
> -1)
1082 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, oldBackgroundPixel
);
1083 if (m_window
&& m_window
->GetBackingPixmap())
1084 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
1085 oldBackgroundPixel
);
1087 if (oldForegroundPixel
> -1)
1089 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, oldForegroundPixel
);
1090 if (m_window
&& m_window
->GetBackingPixmap())
1091 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1092 oldForegroundPixel
);
1098 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1100 wxCHECK_RET( Ok(), "invalid dc" );
1102 // Since X draws from the baseline of the text, must add the text height
1108 slen
= strlen(text
);
1112 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1113 int direction
, descent
;
1114 XCharStruct overall_return
;
1117 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1118 &ascent
, &descent
, &overall_return
);
1121 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1122 &ascent
, &descent
, &overall_return
);
1124 cx
= overall_return
.width
;
1125 cy
= ascent
+ descent
;
1128 // First draw a rectangle representing the text background, if a text
1129 // background is specified
1130 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1132 wxColour oldPenColour
= m_currentColour
;
1133 m_currentColour
= m_textBackgroundColour
;
1134 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1135 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1136 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1137 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1139 // This separation of the big && test required for gcc2.7/HP UX 9.02
1140 // or pixel value can be corrupted!
1141 sameColour
= (sameColour
&&
1142 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1144 if (!sameColour
|| !GetOptimization())
1146 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1147 m_currentColour
= m_textBackgroundColour
;
1149 // Set the GC to the required colour
1152 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1153 if (m_window
&& m_window
->GetBackingPixmap())
1154 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1158 m_textBackgroundColour
= oldPenColour
;
1160 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1161 if (m_window
&& m_window
->GetBackingPixmap())
1162 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1163 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1166 // Now set the text foreground and draw the text
1167 if (m_textForegroundColour
.Ok ())
1169 wxColour oldPenColour
= m_currentColour
;
1170 m_currentColour
= m_textForegroundColour
;
1171 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1172 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1173 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1174 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1175 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1177 if (!sameColour
|| !GetOptimization())
1179 int pixel
= CalculatePixel(m_textForegroundColour
,
1180 m_currentColour
, FALSE
);
1182 // Set the GC to the required colour
1185 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1186 if (m_window
&& m_window
->GetBackingPixmap())
1187 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1191 m_textForegroundColour
= oldPenColour
;
1194 // We need to add the ascent, not the whole height, since X draws at the
1195 // point above the descender.
1198 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1199 (XChar2b
*)(char*) (const char*) text
, slen
);
1202 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1204 if (m_window
&& m_window
->GetBackingPixmap()) {
1207 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1208 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1209 (XChar2b
*)(char*) (const char*) text
, slen
);
1212 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1213 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1217 GetTextExtent (text
, &w
, &h
);
1218 CalcBoundingBox (x
+ w
, y
+ h
);
1219 CalcBoundingBox (x
, y
);
1222 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1226 DrawText(text
, x
, y
);
1230 wxCHECK_RET( Ok(), "invalid dc" );
1232 // Since X draws from the baseline of the text, must add the text height
1238 slen
= strlen(text
);
1242 // Calculate text extent.
1243 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1244 int direction
, descent
;
1245 XCharStruct overall_return
;
1248 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1249 &ascent
, &descent
, &overall_return
);
1252 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1253 &ascent
, &descent
, &overall_return
);
1255 cx
= overall_return
.width
;
1256 cy
= ascent
+ descent
;
1259 wxBitmap
src(cx
, cy
);
1261 dc
.SelectObject(src
);
1262 dc
.SetFont(GetFont());
1263 dc
.SetBackground(*wxWHITE_BRUSH
);
1264 dc
.SetBrush(*wxBLACK_BRUSH
);
1266 dc
.DrawText(text
, 0, 0);
1267 dc
.SetFont(wxNullFont
);
1269 // Calculate the size of the rotated bounding box.
1270 double dx
= cos(angle
/ 180.0 * M_PI
);
1271 double dy
= sin(angle
/ 180.0 * M_PI
);
1272 double x4
= -cy
* dy
;
1273 double y4
= cy
* dx
;
1274 double x3
= cx
* dx
;
1275 double y3
= cx
* dy
;
1276 double x2
= x3
+ x4
;
1277 double y2
= y3
+ y4
;
1281 // Create image from the source bitmap after writing the text into it.
1282 wxImage image
= src
.ConvertToImage();
1284 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1285 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1286 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1287 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1289 // This rotates counterclockwise around the top left corner.
1290 for (int rx
= minx
; rx
< maxx
; rx
++)
1292 for (int ry
= miny
; ry
< maxy
; ry
++)
1294 // transform dest coords to source coords
1295 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1296 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1297 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1299 // draw black pixels, ignore white ones (i.e. transparent b/g)
1300 if (image
.GetRed(sx
, sy
) == 0)
1302 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1307 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1314 // First draw a rectangle representing the text background, if a text
1315 // background is specified
1316 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1318 wxColour oldPenColour
= m_currentColour
;
1319 m_currentColour
= m_textBackgroundColour
;
1320 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1321 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1322 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1323 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1325 // This separation of the big && test required for gcc2.7/HP UX 9.02
1326 // or pixel value can be corrupted!
1327 sameColour
= (sameColour
&&
1328 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1330 if (!sameColour
|| !GetOptimization())
1332 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1333 m_currentColour
= m_textBackgroundColour
;
1335 // Set the GC to the required colour
1338 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1339 if (m_window
&& m_window
->GetBackingPixmap())
1340 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1344 m_textBackgroundColour
= oldPenColour
;
1346 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1347 if (m_window
&& m_window
->GetBackingPixmap())
1348 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1349 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1354 // XXX use pixmap size
1355 GetTextExtent (text
, &w
, &h
);
1356 CalcBoundingBox (x
+ w
, y
+ h
);
1357 CalcBoundingBox (x
, y
);
1360 bool wxWindowDC::CanGetTextExtent() const
1365 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1366 wxCoord
*descent
, wxCoord
*externalLeading
,
1367 wxFont
*font
) const
1369 wxCHECK_RET( Ok(), "invalid dc" );
1371 wxFont
* theFont
= font
;
1373 theFont
= (wxFont
*)&m_font
; // const_cast
1377 // TODO: this should be an error log function
1378 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1380 if (width
) *width
= -1;
1381 if (height
) *height
= -1;
1385 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1387 int direction
, ascent
, descent2
;
1388 XCharStruct overall
;
1393 slen
= str16len(string
);
1396 slen
= strlen(string
);
1400 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1401 &ascent
, &descent2
, &overall
);
1404 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1405 &ascent
, &descent2
, &overall
);
1407 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1408 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1410 *descent
= descent2
;
1411 if (externalLeading
)
1412 *externalLeading
= 0;
1415 wxCoord
wxWindowDC::GetCharWidth() 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
.width
);
1429 wxCoord
wxWindowDC::GetCharHeight() const
1431 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1432 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1434 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1436 int direction
, ascent
, descent
;
1437 XCharStruct overall
;
1438 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1439 &descent
, &overall
);
1440 // return XDEV2LOGREL(overall.ascent + overall.descent);
1441 return XDEV2LOGREL(ascent
+ descent
);
1444 void wxWindowDC::Clear()
1446 wxCHECK_RET( Ok(), "invalid dc" );
1451 m_window
->GetSize(&w
, &h
);
1453 if (m_window
&& m_window
->GetBackingPixmap())
1455 w
= m_window
->GetPixmapWidth();
1456 h
= m_window
->GetPixmapHeight();
1461 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1463 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1464 w
= memDC
->GetBitmap().GetWidth();
1465 h
= memDC
->GetBitmap().GetHeight();
1471 wxBrush saveBrush
= m_brush
;
1472 SetBrush (m_backgroundBrush
);
1474 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1476 if (m_window
&& m_window
->GetBackingPixmap())
1477 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1479 m_brush
= saveBrush
;
1482 void wxWindowDC::Clear(const wxRect
& rect
)
1484 wxCHECK_RET( Ok(), "invalid dc" );
1486 int x
= rect
.x
; int y
= rect
.y
;
1487 int w
= rect
.width
; int h
= rect
.height
;
1489 wxBrush saveBrush
= m_brush
;
1490 SetBrush (m_backgroundBrush
);
1492 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1494 if (m_window
&& m_window
->GetBackingPixmap())
1495 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1497 m_brush
= saveBrush
;
1500 void wxWindowDC::SetFont( const wxFont
&font
)
1502 wxCHECK_RET( Ok(), "invalid dc" );
1508 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1510 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1512 if (m_window
&& m_window
->GetBackingPixmap())
1513 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1518 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1520 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1521 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1523 if (m_window
&& m_window
->GetBackingPixmap())
1524 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1527 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel
)
1529 if (m_logicalFunction
== wxXOR
)
1532 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1533 XSetForeground ((Display
*) m_display
, (GC
) m_gc
,
1534 pixel
^ values
.background
);
1535 if (m_window
&& m_window
->GetBackingPixmap())
1536 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
,
1537 pixel
^ values
.background
);
1541 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1542 if (m_window
&& m_window
->GetBackingPixmap())
1543 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1547 int wxWindowDC::CalculatePixel(wxColour
& colour
, wxColour
& curCol
,
1548 bool roundToWhite
) const
1550 const unsigned char wp
= (unsigned char)255;
1553 if(!m_colour
) // Mono display
1555 unsigned char red
= colour
.Red ();
1556 unsigned char blue
= colour
.Blue ();
1557 unsigned char green
= colour
.Green ();
1559 if((red
== wp
&& blue
== wp
&& green
== wp
) ||
1560 // not black and roundToWhite was specified
1561 ((red
!= 0 || blue
!= 0 || green
!= 0) && roundToWhite
))
1564 pixel
= (int)WhitePixel((Display
*) m_display
,
1565 DefaultScreen((Display
*) m_display
));
1566 curCol
.SetPixel(pixel
);
1567 colour
.SetPixel(pixel
);
1572 pixel
= (int)BlackPixel((Display
*) m_display
,
1573 DefaultScreen((Display
*) m_display
));
1574 curCol
.SetPixel(pixel
);
1575 colour
.SetPixel(pixel
);
1581 pixel
= colour
.AllocColour((Display
*) m_display
);
1582 curCol
.SetPixel(pixel
);
1588 void wxWindowDC::SetPen( const wxPen
&pen
)
1590 wxCHECK_RET( Ok(), "invalid dc" );
1596 wxBitmap oldStipple
= m_currentStipple
;
1597 int oldStyle
= m_currentStyle
;
1598 int oldFill
= m_currentFill
;
1599 int old_pen_width
= m_currentPenWidth
;
1600 int old_pen_join
= m_currentPenJoin
;
1601 int old_pen_cap
= m_currentPenCap
;
1602 int old_pen_nb_dash
= m_currentPenDashCount
;
1603 wxMOTIFDash
*old_pen_dash
= m_currentPenDash
;
1605 wxColour oldPenColour
= m_currentColour
;
1606 m_currentColour
= m_pen
.GetColour ();
1607 m_currentStyle
= m_pen
.GetStyle ();
1608 m_currentFill
= m_pen
.GetStyle (); // TODO?
1609 m_currentPenWidth
= m_pen
.GetWidth ();
1610 m_currentPenJoin
= m_pen
.GetJoin ();
1611 m_currentPenCap
= m_pen
.GetCap ();
1612 m_currentPenDashCount
= m_pen
.GetDashCount();
1613 m_currentPenDash
= (wxMOTIFDash
*)m_pen
.GetDash();
1615 if (m_currentStyle
== wxSTIPPLE
)
1616 m_currentStipple
= * m_pen
.GetStipple ();
1618 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1619 oldFill
== m_currentFill
&&
1620 old_pen_join
== m_currentPenJoin
&&
1621 old_pen_cap
== m_currentPenCap
&&
1622 old_pen_nb_dash
== m_currentPenDashCount
&&
1623 old_pen_dash
== m_currentPenDash
&&
1624 old_pen_width
== m_currentPenWidth
);
1626 bool sameColour
= (oldPenColour
.Ok () &&
1627 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1628 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1629 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1630 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1632 if (!sameStyle
|| !GetOptimization())
1634 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1635 if (scaled_width
< 0)
1641 static const wxMOTIFDash dotted
[] = {2, 5};
1642 static const wxMOTIFDash short_dashed
[] = {4, 4};
1643 static const wxMOTIFDash long_dashed
[] = {4, 8};
1644 static const wxMOTIFDash dotted_dashed
[] = {6, 6, 2, 6};
1646 // We express dash pattern in pen width unit, so we are
1647 // independent of zoom factor and so on...
1649 const wxMOTIFDash
*req_dash
;
1651 switch (m_pen
.GetStyle ())
1654 req_nb_dash
= m_currentPenDashCount
;
1655 req_dash
= m_currentPenDash
;
1656 style
= LineOnOffDash
;
1661 style
= LineOnOffDash
;
1665 req_dash
= short_dashed
;
1666 style
= LineOnOffDash
;
1670 req_dash
= long_dashed
;
1671 style
= LineOnOffDash
;
1675 req_dash
= dotted_dashed
;
1676 style
= LineOnOffDash
;
1683 req_dash
= (wxMOTIFDash
*)NULL
;
1687 if (req_dash
&& req_nb_dash
)
1689 wxMOTIFDash
*real_req_dash
= new wxMOTIFDash
[req_nb_dash
];
1692 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1693 for (int i
= 0; i
< req_nb_dash
; i
++)
1694 real_req_dash
[i
] = req_dash
[i
] * factor
;
1695 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1697 if (m_window
&& m_window
->GetBackingPixmap())
1698 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1699 delete[]real_req_dash
;
1703 // No Memory. We use non-scaled dash pattern...
1704 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1706 if (m_window
&& m_window
->GetBackingPixmap())
1707 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1711 switch (m_pen
.GetCap ())
1713 case wxCAP_PROJECTING
:
1714 cap
= CapProjecting
;
1721 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1725 switch (m_pen
.GetJoin ())
1739 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1741 if (m_window
&& m_window
->GetBackingPixmap())
1742 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1745 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1749 oldStipple
= wxNullBitmap
; // For later reset!!
1751 switch (m_currentFill
)
1753 case wxBDIAGONAL_HATCH
:
1754 if (bdiag
== (Pixmap
) 0)
1755 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1756 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1757 bdiag_bits
, bdiag_width
, bdiag_height
);
1760 case wxFDIAGONAL_HATCH
:
1761 if (fdiag
== (Pixmap
) 0)
1762 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1763 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1764 fdiag_bits
, fdiag_width
, fdiag_height
);
1768 if (cross
== (Pixmap
) 0)
1769 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1770 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1771 cross_bits
, cross_width
, cross_height
);
1774 case wxHORIZONTAL_HATCH
:
1775 if (horiz
== (Pixmap
) 0)
1776 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1777 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1778 horiz_bits
, horiz_width
, horiz_height
);
1781 case wxVERTICAL_HATCH
:
1782 if (verti
== (Pixmap
) 0)
1783 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1784 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1785 verti_bits
, verti_width
, verti_height
);
1788 case wxCROSSDIAG_HATCH
:
1790 if (cdiag
== (Pixmap
) 0)
1791 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1792 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1793 cdiag_bits
, cdiag_width
, cdiag_height
);
1797 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1799 if (m_window
&& m_window
->GetBackingPixmap())
1800 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1802 else if (m_currentStipple
.Ok()
1803 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1805 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1807 if (m_window
&& m_window
->GetBackingPixmap())
1808 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1811 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1815 if (m_currentFill
== wxSTIPPLE
)
1816 fill_style
= FillStippled
;
1817 else if (IS_HATCH (m_currentFill
))
1818 fill_style
= FillStippled
;
1820 fill_style
= FillSolid
;
1821 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1822 if (m_window
&& m_window
->GetBackingPixmap())
1823 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1826 // must test m_logicalFunction, because it involves background!
1827 if (!sameColour
|| !GetOptimization()
1828 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1831 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1832 pixel
= m_backgroundPixel
;
1835 pixel
= CalculatePixel(m_pen
.GetColour(), m_currentColour
, FALSE
);
1838 // Finally, set the GC to the required colour
1840 SetForegroundPixelWithLogicalFunction(pixel
);
1843 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1848 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1850 wxCHECK_RET( Ok(), "invalid dc" );
1854 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1857 int oldFill
= m_currentFill
;
1858 wxBitmap oldStipple
= m_currentStipple
;
1860 m_autoSetting
|= 0x1;
1862 m_currentFill
= m_brush
.GetStyle ();
1863 if (m_currentFill
== wxSTIPPLE
)
1864 m_currentStipple
= * m_brush
.GetStipple ();
1866 wxColour
oldBrushColour(m_currentColour
);
1867 m_currentColour
= m_brush
.GetColour ();
1869 bool sameColour
= (oldBrushColour
.Ok () &&
1870 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1871 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1872 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1873 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1875 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1877 switch (brush
.GetStyle ())
1881 case wxBDIAGONAL_HATCH
:
1882 case wxCROSSDIAG_HATCH
:
1883 case wxFDIAGONAL_HATCH
:
1885 case wxHORIZONTAL_HATCH
:
1886 case wxVERTICAL_HATCH
:
1889 // Chris Breeze 23/07/97: use background mode to determine whether
1890 // fill style should be solid or transparent
1891 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1892 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1893 if (m_window
&& m_window
->GetBackingPixmap())
1894 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1899 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1900 if (m_window
&& m_window
->GetBackingPixmap())
1901 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1905 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1909 switch (m_currentFill
)
1911 case wxBDIAGONAL_HATCH
:
1912 if (bdiag
== (Pixmap
) 0)
1913 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1914 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1915 bdiag_bits
, bdiag_width
, bdiag_height
);
1918 case wxFDIAGONAL_HATCH
:
1919 if (fdiag
== (Pixmap
) 0)
1920 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1921 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1922 fdiag_bits
, fdiag_width
, fdiag_height
);
1926 if (cross
== (Pixmap
) 0)
1927 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1928 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1929 cross_bits
, cross_width
, cross_height
);
1932 case wxHORIZONTAL_HATCH
:
1933 if (horiz
== (Pixmap
) 0)
1934 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1935 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1936 horiz_bits
, horiz_width
, horiz_height
);
1939 case wxVERTICAL_HATCH
:
1940 if (verti
== (Pixmap
) 0)
1941 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1942 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1943 verti_bits
, verti_width
, verti_height
);
1946 case wxCROSSDIAG_HATCH
:
1948 if (cdiag
== (Pixmap
) 0)
1949 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1950 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1951 cdiag_bits
, cdiag_width
, cdiag_height
);
1955 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1957 if (m_window
&& m_window
->GetBackingPixmap())
1958 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1960 // X can forget the stipple value when resizing a window (apparently)
1961 // so always set the stipple.
1962 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1964 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1965 if (m_window
&& m_window
->GetBackingPixmap())
1966 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1969 // must test m_logicalFunction, because it involves background!
1970 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1972 int pixel
= CalculatePixel(m_brush
.GetColour(), m_currentColour
, TRUE
);
1975 SetForegroundPixelWithLogicalFunction(pixel
);
1978 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1981 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1983 wxCHECK_RET( Ok(), "invalid dc" );
1985 m_backgroundBrush
= brush
;
1987 if (!m_backgroundBrush
.Ok())
1990 m_backgroundPixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1992 // New behaviour, 10/2/99: setting the background brush of a DC
1993 // doesn't affect the window background colour.
1995 // XSetWindowBackground doesn't work for non-Window pixmaps
1996 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1997 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2000 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2001 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2002 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, m_backgroundPixel
);
2003 if (m_window
&& m_window
->GetBackingPixmap())
2004 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
,
2008 void wxWindowDC::SetLogicalFunction( int function
)
2010 wxCHECK_RET( Ok(), "invalid dc" );
2015 if (m_logicalFunction
== function
)
2021 x_function
= GXclear
;
2027 x_function
= GXinvert
;
2030 x_function
= GXorReverse
;
2033 x_function
= GXandReverse
;
2042 x_function
= GXandInverted
;
2045 x_function
= GXnoop
;
2051 x_function
= GXequiv
;
2054 x_function
= GXcopyInverted
;
2057 x_function
= GXorInverted
;
2060 x_function
= GXnand
;
2067 x_function
= GXcopy
;
2071 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2072 if (m_window
&& m_window
->GetBackingPixmap())
2073 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2075 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2076 /* MATTHEW: [9] Need to redo pen simply */
2077 m_autoSetting
|= 0x2;
2079 m_logicalFunction
= function
;
2083 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2085 wxCHECK_RET( Ok(), "invalid dc" );
2087 if (m_textForegroundColour
== col
)
2090 m_textForegroundColour
= col
;
2094 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2096 wxCHECK_RET( Ok(), "invalid dc" );
2098 if (m_textBackgroundColour
== col
)
2101 m_textBackgroundColour
= col
;
2102 if (!m_textBackgroundColour
.Ok())
2106 void wxWindowDC::SetBackgroundMode( int mode
)
2108 m_backgroundMode
= mode
;
2111 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2116 /* Use GetXColormap */
2117 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2118 (Colormap
) palette
.GetXColormap());
2120 /* Use wxGetMainColormap */
2121 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2122 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2127 void wxWindowDC::SetDCClipping()
2129 // m_userRegion is the region set by calling SetClippingRegion
2131 if (m_currentRegion
)
2132 XDestroyRegion ((Region
) m_currentRegion
);
2134 // We need to take into account
2135 // clipping imposed on a window by a repaint.
2136 // We'll combine it with the user region. But for now,
2137 // just use the currently-defined user clipping region.
2138 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2139 m_currentRegion
= (WXRegion
) XCreateRegion ();
2141 m_currentRegion
= (WXRegion
) NULL
;
2143 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2144 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2145 else if (m_userRegion
)
2146 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2147 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2148 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2149 (Region
) m_currentRegion
);
2151 if (m_currentRegion
)
2153 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2157 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2162 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2164 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2167 XDestroyRegion ((Region
) m_userRegion
);
2168 m_userRegion
= (WXRegion
) XCreateRegion ();
2172 r
.width
= XLOG2DEVREL(width
);
2173 r
.height
= YLOG2DEVREL(height
);
2174 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2178 // Needs to work differently for Pixmap: without this,
2179 // there's a nasty (Display*) m_display bug. 8/12/94
2180 if (m_window
&& m_window
->GetBackingPixmap())
2182 XRectangle rects
[1];
2183 rects
[0].x
= XLOG2DEV_2(x
);
2184 rects
[0].y
= YLOG2DEV_2(y
);
2185 rects
[0].width
= XLOG2DEVREL(width
);
2186 rects
[0].height
= YLOG2DEVREL(height
);
2187 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2191 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2193 wxRect box
= region
.GetBox();
2195 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2198 XDestroyRegion ((Region
) m_userRegion
);
2199 m_userRegion
= (WXRegion
) XCreateRegion ();
2201 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2205 // Needs to work differently for Pixmap: without this,
2206 // there's a nasty (Display*) m_display bug. 8/12/94
2207 if (m_window
&& m_window
->GetBackingPixmap())
2209 XRectangle rects
[1];
2210 rects
[0].x
= XLOG2DEV_2(box
.x
);
2211 rects
[0].y
= YLOG2DEV_2(box
.y
);
2212 rects
[0].width
= XLOG2DEVREL(box
.width
);
2213 rects
[0].height
= YLOG2DEVREL(box
.height
);
2214 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2219 void wxWindowDC::DestroyClippingRegion()
2221 wxDC::DestroyClippingRegion();
2224 XDestroyRegion ((Region
) m_userRegion
);
2225 m_userRegion
= NULL
;
2230 gc_val
.clip_mask
= None
;
2231 if (m_window
&& m_window
->GetBackingPixmap())
2232 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2235 // Resolution in pixels per logical inch
2236 wxSize
wxWindowDC::GetPPI() const
2238 return wxSize(100, 100);
2241 int wxWindowDC::GetDepth() const
2250 // ----------------------------------------------------------------------------
2252 // ----------------------------------------------------------------------------
2254 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2256 wxRegion
* region
= NULL
;
2258 // Combine all the update rects into a region
2259 const wxRectList
& updateRects(win
->GetUpdateRects());
2260 if ( updateRects
.GetCount() != 0 )
2262 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2264 node
= node
->GetNext() )
2266 wxRect
* rect
= node
->GetData();
2269 region
= new wxRegion(*rect
);
2271 // TODO: is this correct? In SetDCClipping above,
2272 // XIntersectRegion is used to combine paint and user
2273 // regions. XIntersectRegion appears to work in that case...
2274 region
->Union(*rect
);
2280 win
->GetClientSize(&cw
, &ch
);
2281 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2284 win
->SetUpdateRegion(*region
);
2286 wxRegion
& theRegion(win
->GetUpdateRegion());
2287 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2289 // Set the clipping region. Any user-defined region will be combined with this
2290 // one in SetDCClipping.
2291 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2296 wxPaintDC::~wxPaintDC()
2298 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2300 m_window
->ClearUpdateRegion();
2303 // ----------------------------------------------------------------------------
2304 // private functions
2305 // ----------------------------------------------------------------------------
2308 Used when copying between drawables on different (Display*) m_displays. Not
2309 very fast, but better than giving up.
2312 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2313 Drawable src
, Drawable dest
,
2316 unsigned int w
, unsigned int h
,
2317 int destx
, int desty
,
2318 bool more
, XImage
**cache
)
2320 XImage
*image
, *destimage
;
2321 Colormap destcm
, srccm
;
2322 static const int CACHE_SIZE
= 256;
2325 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2326 int k
, cache_pos
, all_cache
;
2328 if (!cache
|| !*cache
)
2329 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2333 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2335 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2336 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2341 for (i
= 0; i
< w
; i
++)
2342 for (j
= 0; j
< h
; j
++) {
2343 unsigned long pixel
;
2346 pixel
= XGetPixel(image
, i
, j
);
2347 for (k
= cache_pos
; k
--; )
2348 if (cachesrc
[k
] == pixel
) {
2349 pixel
= cachedest
[k
];
2353 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2354 if (cachesrc
[k
] == pixel
) {
2355 pixel
= cachedest
[k
];
2359 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2360 XQueryColor(src_display
, srccm
, &xcol
);
2361 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2363 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2365 if (++cache_pos
>= CACHE_SIZE
) {
2371 XPutPixel(destimage
, i
, j
, pixel
);
2374 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2375 XDestroyImage(destimage
);
2380 XDestroyImage(image
);
2385 /* Helper function for 16-bit fonts */
2386 static int str16len(const char *s
)
2390 while (s
[0] && s
[1]) {