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
16 parameters. Therefore, it is impossible to independently maintain
17 the current pen and the current brush. Also, some settings depend
18 on the current logical function. The m_currentFill, etc. instance
19 variables remember state across the brush and pen.
21 Since pens are used more than brushes, the autoSetting flag
22 is used to indicate that a brush was recently used, and SetPen
23 must be called to reinstall the current pen's parameters.
24 If autoSetting includes 0x2, then the pens color may need
25 to be set based on XOR.
27 There is, unfortunately, some confusion between setting the
28 current pen/brush and actually installing the brush/pen parameters.
29 Both functionalies are perform by SetPen and SetBrush. C'est la vie.
33 #pragma implementation "dcclient.h"
36 #include "wx/dcclient.h"
37 #include "wx/dcmemory.h"
38 #include "wx/window.h"
46 #include "wx/motif/private.h"
55 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
57 //-----------------------------------------------------------------------------
59 //-----------------------------------------------------------------------------
61 #define RAD2DEG 57.2957795131
63 // Fudge factor. Obsolete?
64 // No. Robert Roebling
67 //-----------------------------------------------------------------------------
69 //-----------------------------------------------------------------------------
71 #if !USE_SHARED_LIBRARY
72 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
73 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
74 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
77 wxWindowDC::wxWindowDC(void)
80 m_gcBacking
= (WXGC
) 0;
82 m_backgroundPixel
= -1;
83 m_currentPenWidth
= 1;
84 m_currentPenJoin
= -1;
85 m_currentPenDashCount
= -1;
86 m_currentPenDash
= (char*) NULL
;
89 // m_currentBkMode = wxTRANSPARENT;
90 m_colour
= wxColourDisplay();
91 m_display
= (WXDisplay
*) NULL
;
92 m_currentRegion
= (WXRegion
) 0;
93 m_userRegion
= (WXRegion
) 0;
94 m_pixmap
= (WXPixmap
) 0;
96 m_oldFont
= (WXFont
) 0;
99 wxWindowDC::wxWindowDC( wxWindow
*window
)
101 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
105 m_gcBacking
= (WXGC
) 0;
106 m_backgroundPixel
= -1;
107 m_currentPenWidth
= 1;
108 m_currentPenJoin
= -1;
109 m_currentPenDashCount
= -1;
110 m_currentPenDash
= (char*) NULL
;
113 // m_currentBkMode = wxTRANSPARENT;
114 m_colour
= wxColourDisplay();
115 m_currentRegion
= (WXRegion
) 0;
116 m_userRegion
= (WXRegion
) 0;
120 m_display
= window
->GetXDisplay();
121 m_pixmap
= window
->GetXWindow();
122 Display
* display
= (Display
*) m_display
;
124 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
127 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
128 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
129 gcvalues
.graphics_exposures
= False
;
130 gcvalues
.line_width
= 1;
131 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
132 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
135 if (m_window
->GetBackingPixmap())
137 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
138 DefaultScreen (display
)),
139 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
143 m_backgroundPixel
= (int) gcvalues
.background
;
145 // Get the current Font so we can set it back later
147 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
148 m_oldFont
= (WXFont
) valReturn
.font
;
150 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
153 wxWindowDC::~wxWindowDC(void)
155 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
157 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
159 if (m_window
&& m_window
->GetBackingPixmap())
160 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
164 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
168 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
169 m_gcBacking
= (WXGC
) 0;
172 XDestroyRegion ((Region
) m_currentRegion
);
173 m_currentRegion
= (WXRegion
) 0;
176 XDestroyRegion ((Region
) m_userRegion
);
177 m_userRegion
= (WXRegion
) 0;
180 void wxWindowDC::FloodFill( long WXUNUSED(x1
), long WXUNUSED(y1
),
181 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
186 bool wxWindowDC::GetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
192 void wxWindowDC::DrawLine( long x1
, long y1
, long x2
, long y2
)
196 int x1d
, y1d
, x2d
, y2d
;
198 // FreeGetPixelCache();
208 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
210 if (m_window
&& m_window
->GetBackingPixmap())
211 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
212 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
213 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
215 CalcBoundingBox(x1
, y1
);
216 CalcBoundingBox(x2
, y2
);
219 void wxWindowDC::CrossHair( long x
, long y
)
226 int xx
= XLOG2DEV (x
);
227 int yy
= YLOG2DEV (y
);
229 wxDisplaySize (&ww
, &hh
);
230 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
232 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
235 if (m_window
&& m_window
->GetBackingPixmap())
239 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
242 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
248 void wxWindowDC::DrawArc( long x1
, long y1
, long x2
, long y2
, long xc
, long yc
)
252 // FreeGetPixelCache();
254 int xx1
= XLOG2DEV (x1
);
255 int yy1
= YLOG2DEV (y1
);
256 int xx2
= XLOG2DEV (x2
);
257 int yy2
= YLOG2DEV (y2
);
258 int xxc
= XLOG2DEV (xc
);
259 int yyc
= YLOG2DEV (yc
);
260 int xxc_2
= XLOG2DEV_2 (xc
);
261 int yyc_2
= YLOG2DEV_2 (yc
);
265 double radius
= sqrt (dx
* dx
+ dy
* dy
);
266 long r
= (long) radius
;
268 double radius1
, radius2
;
270 if (xx1
== xx2
&& yy1
== yy2
)
275 else if (radius
== 0.0)
276 radius1
= radius2
= 0.0;
285 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
293 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
297 int alpha1
= (int) radius1
;
298 int alpha2
= (int) (radius2
- radius1
);
301 while (alpha2
> 360 * 64)
304 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
307 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
308 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
310 if (m_window
&& m_window
->GetBackingPixmap())
311 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
312 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
316 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
320 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
321 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
323 if (m_window
&& m_window
->GetBackingPixmap())
324 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
325 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
327 CalcBoundingBox (x1
, y1
);
328 CalcBoundingBox (x2
, y2
);
331 void wxWindowDC::DrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
339 wd
= XLOG2DEVREL(width
);
340 hd
= YLOG2DEVREL(height
);
342 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
343 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
344 int start
= int(sa
*64);
345 int end
= int(ea
*64);
346 if (start
<0) start
+=360*64;
347 if (end
<0) end
+=360*64;
348 if (end
>start
) end
-=start
;
349 else end
+=360*64-start
;
351 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
353 m_autoSetting
= TRUE
; // must be reset
356 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
358 if (m_window
&& m_window
->GetBackingPixmap())
359 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
360 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
363 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
367 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
368 if (m_window
&& m_window
->GetBackingPixmap())
369 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
370 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
372 CalcBoundingBox (x
, y
);
373 CalcBoundingBox (x
+ width
, y
+ height
);
376 void wxWindowDC::DrawPoint( long x
, long y
)
380 // FreeGetPixelCache();
382 if (m_pen
.Ok() && m_autoSetting
)
385 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
386 if (m_window
&& m_window
->GetBackingPixmap())
387 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
389 CalcBoundingBox (x
, y
);
392 void wxWindowDC::DrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
396 // FreeGetPixelCache();
398 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
403 XPoint
*xpoints
= new XPoint
[n
];
406 for (i
= 0; i
< n
; i
++)
408 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
409 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
411 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
413 if (m_window
&& m_window
->GetBackingPixmap())
415 for (i
= 0; i
< n
; i
++)
417 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
418 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
420 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
426 void wxWindowDC::DrawLines( wxList
*list
, long xoffset
, long yoffset
)
430 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
432 int n
= list
->Number();
433 wxPoint
*points
= new wxPoint
[n
];
436 for(wxNode
*node
= list
->First(); node
; node
= node
->Next()) {
437 wxPoint
*point
= (wxPoint
*)node
->Data();
438 points
[i
].x
= point
->x
;
439 points
[i
++].y
= point
->y
;
441 DrawLines(n
, points
, xoffset
, yoffset
);
445 void wxWindowDC::DrawPolygon( int n
, wxPoint points
[],
446 long xoffset
, long yoffset
, int fillStyle
)
448 // FreeGetPixelCache();
450 XPoint
*xpoints1
= new XPoint
[n
+ 1];
451 XPoint
*xpoints2
= new XPoint
[n
+ 1];
453 for (i
= 0; i
< n
; i
++)
455 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
456 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
457 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
458 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
459 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
462 // Close figure for XDrawLines (not needed for XFillPolygon)
463 xpoints1
[i
].x
= xpoints1
[0].x
;
464 xpoints1
[i
].y
= xpoints1
[0].y
;
465 xpoints2
[i
].x
= xpoints2
[0].x
;
466 xpoints2
[i
].y
= xpoints2
[0].y
;
468 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
471 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
472 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
473 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
474 if (m_window
&& m_window
->GetBackingPixmap())
476 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
477 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
478 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
479 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
483 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
487 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
489 if (m_window
&& m_window
->GetBackingPixmap())
490 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
497 void wxWindowDC::DrawPolygon( wxList
*list
, long xoffset
,
498 long yoffset
, int fillStyle
)
502 int n
= list
->Number();
503 wxPoint
*points
= new wxPoint
[n
];
506 for(wxNode
*node
= list
->First(); node
; node
= node
->Next()) {
507 wxPoint
*point
= (wxPoint
*)node
->Data();
508 points
[i
].x
= point
->x
;
509 points
[i
++].y
= point
->y
;
511 DrawPolygon(n
, points
, xoffset
, yoffset
,fillStyle
);
515 void wxWindowDC::DrawRectangle( long x
, long y
, long width
, long height
)
519 // FreeGetPixelCache();
521 int xd
, yd
, wfd
, hfd
, wd
, hd
;
525 wfd
= XLOG2DEVREL(width
);
527 hfd
= YLOG2DEVREL(height
);
530 if (wfd
== 0 || hfd
== 0) return;
531 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
532 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
534 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
537 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
539 if (m_window
&& m_window
->GetBackingPixmap())
540 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
541 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
545 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
549 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
551 if (m_window
&& m_window
->GetBackingPixmap())
552 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
553 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
556 CalcBoundingBox (x
, y
);
557 CalcBoundingBox (x
+ width
, y
+ height
);
560 void wxWindowDC::DrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
564 // FreeGetPixelCache();
566 // If radius is negative, it's a proportion of the smaller dimension.
568 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
570 int xd
= XLOG2DEV (x
);
571 int yd
= YLOG2DEV (y
);
572 int rd
= XLOG2DEVREL ((long) radius
);
573 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
574 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
579 // If radius is zero use DrawRectangle() instead to avoid
580 // X drawing errors with small radii
583 DrawRectangle( x
, y
, width
, height
);
587 // Draw nothing if transformed w or h is 0
588 if (wd
== 0 || hd
== 0) return;
590 // CMB: adjust size if outline is drawn otherwise the result is
591 // 1 pixel too wide and high
592 if (m_pen
.GetStyle() != wxTRANSPARENT
)
598 // CMB: ensure dd is not larger than rectangle otherwise we
599 // get an hour glass shape
600 if (rw_d
> wd
) rw_d
= wd
;
601 if (rw_d
> hd
) rw_d
= hd
;
604 // For backing pixmap
605 int xd2
= XLOG2DEV_2 (x
);
606 int yd2
= YLOG2DEV_2 (y
);
607 int rd2
= XLOG2DEVREL ((long) radius
);
608 int wd2
= XLOG2DEVREL (width
) ;
609 int hd2
= YLOG2DEVREL (height
) ;
614 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
618 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
620 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
623 // Arcs start from 3 o'clock, positive angles anticlockwise
625 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
626 rw_d
, rh_d
, 90 * 64, 90 * 64);
628 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
629 // rw_d, rh_d, 0, 90 * 64);
630 rw_d
, rh_d
, 0, 91 * 64);
632 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
634 // rw_d, rh_d, 270 * 64, 90 * 64);
635 rw_d
, rh_d
, 269 * 64, 92 * 64);
637 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
638 rw_d
, rh_d
, 180 * 64, 90 * 64);
640 if (m_window
&& m_window
->GetBackingPixmap())
642 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
643 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
644 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
645 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
647 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
648 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
649 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
650 xd2
+ wd2
- rw_d2
, yd2
,
651 // rw_d2, rh_d2, 0, 90 * 64);
652 rw_d2
, rh_d2
, 0, 91 * 64);
653 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
656 // rw_d2, rh_d2, 270 * 64, 90 * 64);
657 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
658 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
659 xd2
, yd2
+ hd2
- rh_d2
,
660 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
664 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
667 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
668 xd
+ wd
- rd
+ 1, yd
);
669 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
670 xd
+ wd
- rd
, yd
+ hd
);
672 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
674 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
675 xd
+ wd
, yd
+ hd
- rd
+ 1);
676 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
677 rw_d
, rh_d
, 90 * 64, 90 * 64);
678 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
679 // rw_d, rh_d, 0, 90 * 64);
680 rw_d
, rh_d
, 0, 91 * 64);
681 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
683 rw_d
, rh_d
, 269 * 64, 92 * 64);
684 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
685 rw_d
, rh_d
, 180 * 64, 90 * 64);
687 if (m_window
&& m_window
->GetBackingPixmap())
689 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
691 xd2
+ wd2
- rd2
+ 1, yd2
);
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
693 xd2
+ rd2
, yd2
+ hd2
,
694 xd2
+ wd2
- rd2
, yd2
+ hd2
);
696 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
698 xd2
, yd2
+ hd2
- rd2
);
699 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
700 xd2
+ wd2
, yd2
+ rd2
,
701 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
702 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
704 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
705 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
706 xd2
+ wd2
- rw_d2
, yd2
,
707 // rw_d2, rh_d2, 0, 90 * 64);
708 rw_d2
, rh_d2
, 0, 91 * 64);
709 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
712 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
713 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
714 xd2
, yd2
+ hd2
- rh_d2
,
715 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
718 CalcBoundingBox (x
, y
);
719 CalcBoundingBox (x
+ width
, y
+ height
);
724 void wxWindowDC::DrawEllipse( long x
, long y
, long width
, long height
)
728 // Check for negative width and height
741 // FreeGetPixelCache();
743 static const int angle
= 23040;
749 wd
= XLOG2DEVREL(width
) ;
750 hd
= YLOG2DEVREL(height
) ;
752 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
755 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
756 if (m_window
&& m_window
->GetBackingPixmap())
757 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
758 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
759 XLOG2DEVREL (width
) - WX_GC_CF
,
760 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
763 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
767 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
768 if (m_window
&& m_window
->GetBackingPixmap())
769 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
770 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
771 XLOG2DEVREL (width
) - WX_GC_CF
,
772 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
774 CalcBoundingBox (x
, y
);
775 CalcBoundingBox (x
+ width
, y
+ height
);
779 bool wxWindowDC::CanDrawBitmap(void) const
784 /* Used when copying between drawables on different (Display*) m_displays.
785 Not very fast, but better than giving up.
788 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
789 Drawable src
, Drawable dest
,
792 unsigned int w
, unsigned int h
,
793 int destx
, int desty
,
794 bool more
, XImage
**cache
)
796 XImage
*image
, *destimage
;
797 Colormap destcm
, srccm
;
798 #define CACHE_SIZE 256
800 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
801 int k
, cache_pos
, all_cache
;
803 if (!cache
|| !*cache
)
804 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
808 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
810 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
811 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
816 for (i
= 0; i
< w
; i
++)
817 for (j
= 0; j
< h
; j
++) {
821 pixel
= XGetPixel(image
, i
, j
);
822 for (k
= cache_pos
; k
--; )
823 if (cachesrc
[k
] == pixel
) {
824 pixel
= cachedest
[k
];
828 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
829 if (cachesrc
[k
] == pixel
) {
830 pixel
= cachedest
[k
];
834 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
835 XQueryColor(src_display
, srccm
, &xcol
);
836 if (!XAllocColor(dest_display
, destcm
, &xcol
))
838 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
840 if (++cache_pos
>= CACHE_SIZE
) {
846 XPutPixel(destimage
, i
, j
, pixel
);
849 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
850 XDestroyImage(destimage
);
855 XDestroyImage(image
);
858 void wxWindowDC::DrawIcon( const wxIcon
&icon
, long x
, long y
)
862 if (!icon
.Ok()) return;
864 DrawBitmap(icon
, x
, y
, TRUE
);
867 // FreeGetPixelCache();
869 // Be sure that foreground pixels (1) of
870 // the Icon will be painted with pen colour. [m_pen.SetColour()]
871 // Background pixels (0) will be painted with
872 // last selected background color. [::SetBackground]
873 if (m_pen
.Ok() && m_autoSetting
)
877 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
878 width
= icon
.GetWidth();
879 height
= icon
.GetHeight();
880 if (icon
.GetDisplay() == m_display
)
882 if (icon
.GetDepth() <= 1)
884 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
886 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
890 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
892 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
896 if (m_window
&& m_window
->GetBackingPixmap())
898 if (icon
.GetDepth() <= 1)
900 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
901 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
905 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
907 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
910 } else { /* Remote copy (different (Display*) m_displays) */
911 XImage
*cache
= NULL
;
912 if (m_window
&& m_window
->GetBackingPixmap())
913 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
914 (GC
) m_gcBacking
, 0, 0, width
, height
,
915 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
916 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
918 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
920 CalcBoundingBox (x
, y
);
924 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
925 bool wxWindowDC::Blit( long xdest
, long ydest
, long width
, long height
,
926 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
928 if (!Ok()) return FALSE
;
930 wxASSERT_MSG( (source
->IsKindOf(CLASSINFO(wxWindowDC
))), "Blit source DC must be wxWindowDC or derived class." );
932 wxWindowDC
* sourceDC
= (wxWindowDC
*) source
;
934 // FreeGetPixelCache();
936 // Be sure that foreground pixels (1) of
937 // the Icon will be painted with pen colour. [m_pen.SetColour()]
938 // Background pixels (0) will be painted with
939 // last selected background color. [::SetBackground]
940 if (m_pen
.Ok() && m_autoSetting
)
943 // Do bitmap scaling if necessary
945 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
946 Pixmap sourcePixmap
= (Pixmap
) NULL
;
947 double scaleX
, scaleY
;
948 GetUserScale(& scaleX
, & scaleY
);
950 // Sorry, can't scale masks just yet
951 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
953 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
954 wxBitmap
& bitmap
= memDC
->GetBitmap();
956 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
958 wxImage
image(bitmap
);
961 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
965 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
966 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
968 image
= image
.Scale(scaledW
, scaledH
);
969 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
970 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
974 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
976 if (m_pixmap
&& sourcePixmap
)
979 int orig
= m_logicalFunction
;
981 SetLogicalFunction (rop
);
983 if (m_display
!= sourceDC
->m_display
)
985 XImage
*cache
= NULL
;
987 if (m_window
&& m_window
->GetBackingPixmap())
988 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
989 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
991 source
->LogicalToDeviceX (xsrc
),
992 source
->LogicalToDeviceY (ysrc
),
993 source
->LogicalToDeviceXRel(width
),
994 source
->LogicalToDeviceYRel(height
),
995 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
998 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1000 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1001 wxBitmap
& sel
= memDC
->GetBitmap();
1002 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1004 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1005 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1009 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1010 source
->LogicalToDeviceX (xsrc
),
1011 source
->LogicalToDeviceY (ysrc
),
1012 source
->LogicalToDeviceXRel(width
),
1013 source
->LogicalToDeviceYRel(height
),
1014 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
1019 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1020 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1025 if (m_window
&& m_window
->GetBackingPixmap())
1027 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
1028 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
1030 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1031 source
->LogicalToDeviceX (xsrc
),
1032 source
->LogicalToDeviceY (ysrc
),
1033 source
->LogicalToDeviceXRel(width
),
1034 source
->LogicalToDeviceYRel(height
),
1035 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
1039 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1040 source
->LogicalToDeviceX (xsrc
),
1041 source
->LogicalToDeviceY (ysrc
),
1042 source
->LogicalToDeviceXRel(width
),
1043 source
->LogicalToDeviceYRel(height
),
1044 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
1047 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
1049 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1050 wxBitmap
& sel
= memDC
->GetBitmap();
1051 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1053 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1054 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1058 // Check if we're copying from a mono bitmap
1059 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1060 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1062 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1063 source
->LogicalToDeviceX (xsrc
),
1064 source
->LogicalToDeviceY (ysrc
),
1065 source
->LogicalToDeviceXRel(width
),
1066 source
->LogicalToDeviceYRel(height
),
1067 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1071 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1072 source
->LogicalToDeviceX (xsrc
),
1073 source
->LogicalToDeviceY (ysrc
),
1074 source
->LogicalToDeviceXRel(width
),
1075 source
->LogicalToDeviceYRel(height
),
1076 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1081 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1082 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1085 } /* Remote/local (Display*) m_display */
1086 CalcBoundingBox (xdest
, ydest
);
1087 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1089 SetLogicalFunction(orig
);
1091 if (scaledBitmap
) delete scaledBitmap
;
1095 if (scaledBitmap
) delete scaledBitmap
;
1100 /* Helper function for 16-bit fonts */
1101 static int str16len(const char *s
)
1105 while (s
[0] && s
[1]) {
1113 void wxWindowDC::DrawText( const wxString
&text
, long x
, long y
, bool use16
)
1117 // Since X draws from the baseline of the text, must
1118 // add the text height
1125 slen
= str16len(text
);
1127 slen
= strlen(text
);
1131 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1132 int direction
, descent
;
1133 XCharStruct overall_return
;
1135 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1136 &ascent
, &descent
, &overall_return
);
1138 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1139 &ascent
, &descent
, &overall_return
);
1140 cx
= overall_return
.width
;
1141 cy
= ascent
+ descent
;
1144 // First draw a rectangle representing the text background,
1145 // if a text background is specified
1146 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1148 wxColour oldPenColour
= m_currentColour
;
1149 m_currentColour
= m_textBackgroundColour
;
1150 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1151 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1152 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1153 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1155 // This separation of the big && test required for gcc2.7/HP UX 9.02
1156 // or pixel value can be corrupted!
1157 sameColour
= (sameColour
&&
1158 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1160 if (!sameColour
|| !GetOptimization())
1162 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1163 m_currentColour
= m_textBackgroundColour
;
1165 // Set the GC to the required colour
1168 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1169 if (m_window
&& m_window
->GetBackingPixmap())
1170 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1174 m_textBackgroundColour
= oldPenColour
;
1176 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1177 if (m_window
&& m_window
->GetBackingPixmap())
1178 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1179 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1182 // Now set the text foreground and draw the text
1183 if (m_textForegroundColour
.Ok ())
1185 wxColour oldPenColour
= m_currentColour
;
1186 m_currentColour
= m_textForegroundColour
;
1187 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1188 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1189 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1190 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1191 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1193 if (!sameColour
|| !GetOptimization())
1196 if (!m_colour
) // Mono display
1198 // Unless foreground is really white, draw it in black
1199 unsigned char red
= m_textForegroundColour
.Red ();
1200 unsigned char blue
= m_textForegroundColour
.Blue ();
1201 unsigned char green
= m_textForegroundColour
.Green ();
1202 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1203 && green
== (unsigned char) 255)
1205 m_currentColour
= *wxWHITE
;
1206 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1207 m_currentColour
.SetPixel(pixel
);
1208 m_textForegroundColour
.SetPixel(pixel
);
1212 m_currentColour
= *wxBLACK
;
1213 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1214 m_currentColour
.SetPixel(pixel
);
1215 m_textForegroundColour
.SetPixel(pixel
);
1220 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1221 m_currentColour
.SetPixel(pixel
);
1224 // Set the GC to the required colour
1227 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1228 if (m_window
&& m_window
->GetBackingPixmap())
1229 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1233 m_textForegroundColour
= oldPenColour
;
1236 // We need to add the ascent, not the whole height, since X draws
1237 // at the point above the descender.
1239 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1240 (XChar2b
*)(char*) (const char*) text
, slen
);
1242 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1245 if (m_window
&& m_window
->GetBackingPixmap()) {
1247 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1248 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1249 (XChar2b
*)(char*) (const char*) text
, slen
);
1251 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1252 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1256 GetTextExtent (text
, &w
, &h
);
1257 CalcBoundingBox (x
+ w
, y
+ h
);
1258 CalcBoundingBox (x
, y
);
1261 bool wxWindowDC::CanGetTextExtent(void) const
1266 void wxWindowDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
1267 long *descent
, long *externalLeading
,
1268 wxFont
*font
, bool use16
)
1272 wxFont
* theFont
= font
;
1278 // TODO: this should be an error log function
1279 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1286 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1288 int direction
, ascent
, descent2
;
1289 XCharStruct overall
;
1292 if (use16
) slen
= str16len(string
); else slen
= strlen(string
);
1295 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1296 &ascent
, &descent2
, &overall
);
1298 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1299 &ascent
, &descent2
, &overall
);
1301 *width
= XDEV2LOGREL (overall
.width
);
1302 *height
= YDEV2LOGREL (ascent
+ descent2
);
1304 *descent
= descent2
;
1305 if (externalLeading
)
1306 *externalLeading
= 0;
1309 long wxWindowDC::GetCharWidth(void)
1311 if (!Ok()) return 0;
1316 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1318 int direction
, ascent
, descent
;
1319 XCharStruct overall
;
1320 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1321 &descent
, &overall
);
1322 return XDEV2LOGREL(overall
.width
);
1325 long wxWindowDC::GetCharHeight(void)
1327 if (!Ok()) return 0;
1332 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1334 int direction
, ascent
, descent
;
1335 XCharStruct overall
;
1336 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1337 &descent
, &overall
);
1338 // return XDEV2LOGREL(overall.ascent + overall.descent);
1339 return XDEV2LOGREL(ascent
+ descent
);
1342 void wxWindowDC::Clear(void)
1349 m_window
->GetSize(&w
, &h
);
1351 if (m_window
&& m_window
->GetBackingPixmap())
1353 w
= m_window
->GetPixmapWidth();
1354 h
= m_window
->GetPixmapHeight();
1359 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1361 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1362 w
= memDC
->GetBitmap().GetWidth();
1363 h
= memDC
->GetBitmap().GetHeight();
1369 wxBrush saveBrush
= m_brush
;
1370 SetBrush (m_backgroundBrush
);
1372 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1374 if (m_window
&& m_window
->GetBackingPixmap())
1375 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1377 m_brush
= saveBrush
;
1380 void wxWindowDC::Clear(const wxRect
& rect
)
1384 int x
= rect
.x
; int y
= rect
.y
;
1385 int w
= rect
.width
; int h
= rect
.height
;
1387 wxBrush saveBrush
= m_brush
;
1388 SetBrush (m_backgroundBrush
);
1390 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1392 if (m_window
&& m_window
->GetBackingPixmap())
1393 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1395 m_brush
= saveBrush
;
1398 void wxWindowDC::SetFont( const wxFont
&font
)
1406 if ((m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
1408 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1410 if (m_window
&& m_window
->GetBackingPixmap())
1411 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1416 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1418 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1419 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1421 if (m_window
&& m_window
->GetBackingPixmap())
1422 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1425 void wxWindowDC::SetPen( const wxPen
&pen
)
1433 wxBitmap oldStipple
= m_currentStipple
;
1434 int oldStyle
= m_currentStyle
;
1435 int oldFill
= m_currentFill
;
1436 int old_pen_width
= m_currentPenWidth
;
1437 int old_pen_join
= m_currentPenJoin
;
1438 int old_pen_cap
= m_currentPenCap
;
1439 int old_pen_nb_dash
= m_currentPenDashCount
;
1440 char *old_pen_dash
= m_currentPenDash
;
1442 wxColour oldPenColour
= m_currentColour
;
1443 m_currentColour
= m_pen
.GetColour ();
1444 m_currentStyle
= m_pen
.GetStyle ();
1445 m_currentFill
= m_pen
.GetStyle (); // TODO?
1446 m_currentPenWidth
= m_pen
.GetWidth ();
1447 m_currentPenJoin
= m_pen
.GetJoin ();
1448 m_currentPenCap
= m_pen
.GetCap ();
1449 m_currentPenDashCount
= m_pen
.GetDashCount();
1450 m_currentPenDash
= m_pen
.GetDash();
1452 if (m_currentStyle
== wxSTIPPLE
)
1453 m_currentStipple
= * m_pen
.GetStipple ();
1455 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1456 oldFill
== m_currentFill
&&
1457 old_pen_join
== m_currentPenJoin
&&
1458 old_pen_cap
== m_currentPenCap
&&
1459 old_pen_nb_dash
== m_currentPenDashCount
&&
1460 old_pen_dash
== m_currentPenDash
&&
1461 old_pen_width
== m_currentPenWidth
);
1463 bool sameColour
= (oldPenColour
.Ok () &&
1464 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1465 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1466 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1467 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1469 if (!sameStyle
|| !GetOptimization())
1471 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1472 if (scaled_width
< 0)
1478 static char dotted
[] =
1480 static char short_dashed
[] =
1482 static char long_dashed
[] =
1484 static char dotted_dashed
[] =
1487 // We express dash pattern in pen width unit, so we are
1488 // independent of zoom factor and so on...
1492 switch (m_pen
.GetStyle ())
1495 req_nb_dash
= m_currentPenDashCount
;
1496 req_dash
= m_currentPenDash
;
1497 style
= LineOnOffDash
;
1502 style
= LineOnOffDash
;
1506 req_dash
= short_dashed
;
1507 style
= LineOnOffDash
;
1511 req_dash
= long_dashed
;
1512 style
= LineOnOffDash
;
1516 req_dash
= dotted_dashed
;
1517 style
= LineOnOffDash
;
1528 if (req_dash
&& req_nb_dash
)
1530 char *real_req_dash
= new char[req_nb_dash
];
1533 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1534 for (int i
= 0; i
< req_nb_dash
; i
++)
1535 real_req_dash
[i
] = req_dash
[i
] * factor
;
1536 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1538 if (m_window
&& m_window
->GetBackingPixmap())
1539 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1540 delete[]real_req_dash
;
1544 // No Memory. We use non-scaled dash pattern...
1545 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1547 if (m_window
&& m_window
->GetBackingPixmap())
1548 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1552 switch (m_pen
.GetCap ())
1554 case wxCAP_PROJECTING
:
1555 cap
= CapProjecting
;
1562 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1566 switch (m_pen
.GetJoin ())
1580 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1582 if (m_window
&& m_window
->GetBackingPixmap())
1583 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1586 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1590 oldStipple
= wxNullBitmap
; // For later reset!!
1592 switch (m_currentFill
)
1594 case wxBDIAGONAL_HATCH
:
1595 if (bdiag
== (Pixmap
) 0)
1596 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1597 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1598 bdiag_bits
, bdiag_width
, bdiag_height
);
1601 case wxFDIAGONAL_HATCH
:
1602 if (fdiag
== (Pixmap
) 0)
1603 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1604 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1605 fdiag_bits
, fdiag_width
, fdiag_height
);
1609 if (cross
== (Pixmap
) 0)
1610 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1611 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1612 cross_bits
, cross_width
, cross_height
);
1615 case wxHORIZONTAL_HATCH
:
1616 if (horiz
== (Pixmap
) 0)
1617 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1618 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1619 horiz_bits
, horiz_width
, horiz_height
);
1622 case wxVERTICAL_HATCH
:
1623 if (verti
== (Pixmap
) 0)
1624 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1625 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1626 verti_bits
, verti_width
, verti_height
);
1629 case wxCROSSDIAG_HATCH
:
1631 if (cdiag
== (Pixmap
) 0)
1632 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1633 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1634 cdiag_bits
, cdiag_width
, cdiag_height
);
1638 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1640 if (m_window
&& m_window
->GetBackingPixmap())
1641 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1643 else if (m_currentStipple
.Ok()
1644 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1646 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1648 if (m_window
&& m_window
->GetBackingPixmap())
1649 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1652 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1656 if (m_currentFill
== wxSTIPPLE
)
1657 fill_style
= FillStippled
;
1658 else if (IS_HATCH (m_currentFill
))
1659 fill_style
= FillStippled
;
1661 fill_style
= FillSolid
;
1662 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1663 if (m_window
&& m_window
->GetBackingPixmap())
1664 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1667 // must test m_logicalFunction, because it involves background!
1668 if (!sameColour
|| !GetOptimization()
1669 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1672 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1673 pixel
= m_backgroundPixel
;
1676 unsigned char red
= m_pen
.GetColour ().Red ();
1677 unsigned char blue
= m_pen
.GetColour ().Blue ();
1678 unsigned char green
= m_pen
.GetColour ().Green ();
1679 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1680 && green
== (unsigned char) 255)
1682 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1683 m_currentColour
= *wxWHITE
;
1684 m_pen
.GetColour().SetPixel(pixel
);
1685 m_currentColour
.SetPixel(pixel
);
1689 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1690 m_currentColour
= *wxBLACK
;
1691 m_pen
.GetColour().SetPixel(pixel
);
1696 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1697 m_currentColour
.SetPixel(pixel
);
1700 // Finally, set the GC to the required colour
1703 if (m_logicalFunction
== wxXOR
)
1706 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1707 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1708 if (m_window
&& m_window
->GetBackingPixmap())
1709 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1713 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1714 if (m_window
&& m_window
->GetBackingPixmap())
1715 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1720 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1725 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1731 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1734 int oldFill
= m_currentFill
;
1735 wxBitmap oldStipple
= m_currentStipple
;
1737 m_autoSetting
|= 0x1;
1739 m_currentFill
= m_brush
.GetStyle ();
1740 if (m_currentFill
== wxSTIPPLE
)
1741 m_currentStipple
= * m_brush
.GetStipple ();
1743 wxColour
oldBrushColour(m_currentColour
);
1744 m_currentColour
= m_brush
.GetColour ();
1746 bool sameColour
= (oldBrushColour
.Ok () &&
1747 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1748 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1749 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1750 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1752 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1754 switch (brush
.GetStyle ())
1758 case wxBDIAGONAL_HATCH
:
1759 case wxCROSSDIAG_HATCH
:
1760 case wxFDIAGONAL_HATCH
:
1762 case wxHORIZONTAL_HATCH
:
1763 case wxVERTICAL_HATCH
:
1766 // Chris Breeze 23/07/97: use background mode to determine whether
1767 // fill style should be solid or transparent
1768 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1769 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1770 if (m_window
&& m_window
->GetBackingPixmap())
1771 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1776 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1777 if (m_window
&& m_window
->GetBackingPixmap())
1778 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1782 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1786 switch (m_currentFill
)
1788 case wxBDIAGONAL_HATCH
:
1789 if (bdiag
== (Pixmap
) 0)
1790 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1791 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1792 bdiag_bits
, bdiag_width
, bdiag_height
);
1795 case wxFDIAGONAL_HATCH
:
1796 if (fdiag
== (Pixmap
) 0)
1797 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1798 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1799 fdiag_bits
, fdiag_width
, fdiag_height
);
1803 if (cross
== (Pixmap
) 0)
1804 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1805 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1806 cross_bits
, cross_width
, cross_height
);
1809 case wxHORIZONTAL_HATCH
:
1810 if (horiz
== (Pixmap
) 0)
1811 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1812 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1813 horiz_bits
, horiz_width
, horiz_height
);
1816 case wxVERTICAL_HATCH
:
1817 if (verti
== (Pixmap
) 0)
1818 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1819 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1820 verti_bits
, verti_width
, verti_height
);
1823 case wxCROSSDIAG_HATCH
:
1825 if (cdiag
== (Pixmap
) 0)
1826 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1827 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1828 cdiag_bits
, cdiag_width
, cdiag_height
);
1832 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1834 if (m_window
&& m_window
->GetBackingPixmap())
1835 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1837 // X can forget the stipple value when resizing a window (apparently)
1838 // so always set the stipple.
1839 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1841 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1842 if (m_window
&& m_window
->GetBackingPixmap())
1843 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1846 // must test m_logicalFunction, because it involves background!
1847 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1852 // Policy - on a monochrome screen, all brushes are white,
1853 // except when they're REALLY black!!!
1854 unsigned char red
= m_brush
.GetColour ().Red ();
1855 unsigned char blue
= m_brush
.GetColour ().Blue ();
1856 unsigned char green
= m_brush
.GetColour ().Green ();
1858 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1859 && green
== (unsigned char) 0)
1861 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1862 m_currentColour
= *wxBLACK
;
1863 m_brush
.GetColour().SetPixel(pixel
);
1864 m_currentColour
.SetPixel(pixel
);
1868 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1869 m_currentColour
= *wxWHITE
;
1870 m_brush
.GetColour().SetPixel(pixel
);
1871 m_currentColour
.SetPixel(pixel
);
1874 // N.B. comment out the above line and uncomment the following lines
1875 // if you want non-white colours to be black on a monochrome display.
1877 if (red == (unsigned char )255 && blue == (unsigned char)255
1878 && green == (unsigned char)255)
1879 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1881 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1884 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1886 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1887 m_currentColour
.SetPixel(pixel
);
1891 // Finally, set the GC to the required colour
1892 if (m_logicalFunction
== wxXOR
)
1895 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1896 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1897 if (m_window
&& m_window
->GetBackingPixmap())
1898 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1902 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1903 if (m_window
&& m_window
->GetBackingPixmap())
1904 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1909 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1912 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1916 m_backgroundBrush
= brush
;
1918 if (!m_backgroundBrush
.Ok())
1921 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1923 // New behaviour, 10/2/99: setting the background brush of a DC
1924 // doesn't affect the window background colour.
1926 // XSetWindowBackground doesn't work for non-Window pixmaps
1927 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1928 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1931 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1932 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1933 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1934 if (m_window
&& m_window
->GetBackingPixmap())
1935 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1938 void wxWindowDC::SetLogicalFunction( int function
)
1943 if (m_logicalFunction
== function
)
1949 x_function
= GXclear
;
1955 x_function
= GXinvert
;
1958 x_function
= GXorReverse
;
1961 x_function
= GXandReverse
;
1970 x_function
= GXandInverted
;
1973 x_function
= GXnoop
;
1979 x_function
= GXequiv
;
1982 x_function
= GXcopyInverted
;
1985 x_function
= GXorInverted
;
1988 x_function
= GXnand
;
1995 x_function
= GXcopy
;
1999 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2000 if (m_window
&& m_window
->GetBackingPixmap())
2001 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2003 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2004 /* MATTHEW: [9] Need to redo pen simply */
2005 m_autoSetting
|= 0x2;
2007 m_logicalFunction
= function
;
2011 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2015 if (m_textForegroundColour
== col
) return;
2017 m_textForegroundColour
= col
;
2021 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2025 if (m_textBackgroundColour
== col
) return;
2027 m_textBackgroundColour
= col
;
2028 if (!m_textBackgroundColour
.Ok()) return;
2031 void wxWindowDC::SetBackgroundMode( int mode
)
2033 m_backgroundMode
= mode
;
2037 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2042 /* Use GetXColormap */
2043 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2044 (Colormap
) palette
.GetXColormap());
2046 /* Use wxGetMainColormap */
2047 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2048 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2053 void wxWindowDC:: SetDCClipping ()
2055 // m_userRegion is the region set by calling SetClippingRegion
2057 if (m_currentRegion
)
2058 XDestroyRegion ((Region
) m_currentRegion
);
2060 // We need to take into account
2061 // clipping imposed on a window by a repaint.
2062 // We'll combine it with the user region. But for now,
2063 // just use the currently-defined user clipping region.
2064 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2065 m_currentRegion
= (WXRegion
) XCreateRegion ();
2067 m_currentRegion
= (WXRegion
) NULL
;
2069 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2070 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2071 else if (m_userRegion
)
2072 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2073 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2074 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2075 (Region
) m_currentRegion
);
2077 if (m_currentRegion
)
2079 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2083 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2088 void wxWindowDC::SetClippingRegion( long x
, long y
, long width
, long height
)
2090 wxDC::SetClippingRegion( x
, y
, width
, height
);
2093 XDestroyRegion ((Region
) m_userRegion
);
2094 m_userRegion
= (WXRegion
) XCreateRegion ();
2098 r
.width
= XLOG2DEVREL(width
);
2099 r
.height
= YLOG2DEVREL(height
);
2100 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2104 // Needs to work differently for Pixmap: without this,
2105 // there's a nasty (Display*) m_display bug. 8/12/94
2106 if (m_window
&& m_window
->GetBackingPixmap())
2108 XRectangle rects
[1];
2109 rects
[0].x
= XLOG2DEV_2(x
);
2110 rects
[0].y
= YLOG2DEV_2(y
);
2111 rects
[0].width
= XLOG2DEVREL(width
);
2112 rects
[0].height
= YLOG2DEVREL(height
);
2113 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2117 void wxWindowDC::SetClippingRegion( const wxRegion
& region
)
2119 wxRect box
= region
.GetBox();
2121 wxDC::SetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2124 XDestroyRegion ((Region
) m_userRegion
);
2125 m_userRegion
= (WXRegion
) XCreateRegion ();
2127 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2131 // Needs to work differently for Pixmap: without this,
2132 // there's a nasty (Display*) m_display bug. 8/12/94
2133 if (m_window
&& m_window
->GetBackingPixmap())
2135 XRectangle rects
[1];
2136 rects
[0].x
= XLOG2DEV_2(box
.x
);
2137 rects
[0].y
= YLOG2DEV_2(box
.y
);
2138 rects
[0].width
= XLOG2DEVREL(box
.width
);
2139 rects
[0].height
= YLOG2DEVREL(box
.height
);
2140 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2145 void wxWindowDC::DestroyClippingRegion(void)
2147 wxDC::DestroyClippingRegion();
2150 XDestroyRegion ((Region
) m_userRegion
);
2151 m_userRegion
= NULL
;
2156 gc_val
.clip_mask
= None
;
2157 if (m_window
&& m_window
->GetBackingPixmap())
2158 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2161 // ----------------------------------- spline code ----------------------------------------
2163 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2164 double a3
, double b3
, double a4
, double b4
);
2165 void wx_clear_stack(void);
2166 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2167 double *y3
, double *x4
, double *y4
);
2168 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2169 double x4
, double y4
);
2170 static bool wx_spline_add_point(double x
, double y
);
2171 static void wx_spline_draw_point_array(wxDC
*dc
);
2173 wxList wx_spline_point_list
;
2175 #define half(z1, z2) ((z1+z2)/2.0)
2178 /* iterative version */
2180 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2183 register double xmid
, ymid
;
2184 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2187 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2189 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2190 xmid
= (double)half(x2
, x3
);
2191 ymid
= (double)half(y2
, y3
);
2192 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2193 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2194 wx_spline_add_point( x1
, y1
);
2195 wx_spline_add_point( xmid
, ymid
);
2197 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2198 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2199 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2200 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2205 /* utilities used by spline drawing routines */
2207 typedef struct wx_spline_stack_struct
{
2208 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2211 #define SPLINE_STACK_DEPTH 20
2212 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2213 static Stack
*wx_stack_top
;
2214 static int wx_stack_count
;
2216 void wx_clear_stack(void)
2218 wx_stack_top
= wx_spline_stack
;
2222 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2224 wx_stack_top
->x1
= x1
;
2225 wx_stack_top
->y1
= y1
;
2226 wx_stack_top
->x2
= x2
;
2227 wx_stack_top
->y2
= y2
;
2228 wx_stack_top
->x3
= x3
;
2229 wx_stack_top
->y3
= y3
;
2230 wx_stack_top
->x4
= x4
;
2231 wx_stack_top
->y4
= y4
;
2236 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2237 double *x3
, double *y3
, double *x4
, double *y4
)
2239 if (wx_stack_count
== 0)
2243 *x1
= wx_stack_top
->x1
;
2244 *y1
= wx_stack_top
->y1
;
2245 *x2
= wx_stack_top
->x2
;
2246 *y2
= wx_stack_top
->y2
;
2247 *x3
= wx_stack_top
->x3
;
2248 *y3
= wx_stack_top
->y3
;
2249 *x4
= wx_stack_top
->x4
;
2250 *y4
= wx_stack_top
->y4
;
2254 static bool wx_spline_add_point(double x
, double y
)
2256 wxPoint
*point
= new wxPoint
;
2259 wx_spline_point_list
.Append((wxObject
*)point
);
2263 static void wx_spline_draw_point_array(wxDC
*dc
)
2265 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2266 wxNode
*node
= wx_spline_point_list
.First();
2269 wxPoint
*point
= (wxPoint
*)node
->Data();
2272 node
= wx_spline_point_list
.First();
2276 void wxWindowDC::DrawSpline( wxList
*points
)
2279 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2280 double x1
, y1
, x2
, y2
;
2282 wxNode
*node
= points
->First();
2283 p
= (wxPoint
*)node
->Data();
2288 node
= node
->Next();
2289 p
= (wxPoint
*)node
->Data();
2293 cx1
= (double)((x1
+ x2
) / 2);
2294 cy1
= (double)((y1
+ y2
) / 2);
2295 cx2
= (double)((cx1
+ x2
) / 2);
2296 cy2
= (double)((cy1
+ y2
) / 2);
2298 wx_spline_add_point(x1
, y1
);
2300 while ((node
= node
->Next()) != NULL
)
2302 p
= (wxPoint
*)node
->Data();
2307 cx4
= (double)(x1
+ x2
) / 2;
2308 cy4
= (double)(y1
+ y2
) / 2;
2309 cx3
= (double)(x1
+ cx4
) / 2;
2310 cy3
= (double)(y1
+ cy4
) / 2;
2312 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2316 cx2
= (double)(cx1
+ x2
) / 2;
2317 cy2
= (double)(cy1
+ y2
) / 2;
2320 wx_spline_add_point( cx1
, cy1
);
2321 wx_spline_add_point( x2
, y2
);
2323 wx_spline_draw_point_array( this );
2330 wxPaintDC::wxPaintDC(wxWindow
* win
): wxWindowDC(win
)
2332 wxRegion
* region
= NULL
;
2334 // Combine all the update rects into a region
2335 if (win
->m_updateRects
.Number() > 0)
2338 for (i
= 0; i
< win
->m_updateRects
.Number(); i
++)
2340 wxRect
* rect
= (wxRect
*) win
->m_updateRects
.Nth(i
)->Data();
2342 cout << "wxPaintDC. wxRect: " << rect->x << ", " << rect->y << ", ";
2343 cout << rect->width << ", " << rect->height << "\n\n";
2347 region
= new wxRegion(*rect
);
2349 // TODO: is this correct? In SetDCClipping above,
2350 // XIntersectRegion is used to combine paint and user
2351 // regions. XIntersectRegion appears to work in that case...
2352 region
->Union(*rect
);
2358 win
->GetClientSize(&cw
, &ch
);
2359 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2362 win
->m_updateRegion
= *region
;
2364 // Set the clipping region. Any user-defined region will be combined with this
2365 // one in SetDCClipping.
2366 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2371 wxPaintDC::~wxPaintDC()
2373 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2375 m_window
->m_updateRegion
.Clear();