1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 About pens, brushes, and the autoSetting flag:
15 Under X, pens and brushes control some of the same X drawing parameters.
16 Therefore, it is impossible to independently maintain the current pen and the
17 current brush. Also, some settings depend on the current logical function. The
18 m_currentFill, etc. instance variables remember state across the brush and
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
31 // ============================================================================
33 // ============================================================================
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
40 #pragma implementation "dcclient.h"
43 #include "wx/dcclient.h"
44 #include "wx/dcmemory.h"
45 #include "wx/window.h"
52 #pragma message disable nosimpint
56 #pragma message enable nosimpint
59 #include "wx/motif/private.h"
62 #include <float.h> // for M_PI
72 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 // Fudge factor (VZ: what??)
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
86 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
87 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
89 // ----------------------------------------------------------------------------
91 // ----------------------------------------------------------------------------
93 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
94 Drawable src
, Drawable dest
,
97 unsigned int w
, unsigned int h
,
99 bool more
, XImage
**cache
);
101 // ============================================================================
103 // ============================================================================
106 * compare two doubles and return the larger rounded
109 static int roundmax(double a
, double b
)
111 return (int)((a
> b
? a
: b
) + 0.5);
115 * compare two doubles and return the smaller rounded
118 static int roundmin(double a
, double b
)
120 return (int)((a
< b
? a
: b
) - 0.5);
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
128 wxWindowDC::wxWindowDC()
131 m_gcBacking
= (WXGC
) 0;
133 m_backgroundPixel
= -1;
134 m_currentPenWidth
= 1;
135 m_currentPenJoin
= -1;
136 m_currentPenDashCount
= -1;
137 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
140 // m_currentBkMode = wxTRANSPARENT;
141 m_colour
= wxColourDisplay();
142 m_display
= (WXDisplay
*) NULL
;
143 m_currentRegion
= (WXRegion
) 0;
144 m_userRegion
= (WXRegion
) 0;
145 m_pixmap
= (WXPixmap
) 0;
147 m_oldFont
= (WXFont
) 0;
150 wxWindowDC::wxWindowDC( wxWindow
*window
)
152 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
155 m_font
= window
->GetFont();
157 m_gcBacking
= (WXGC
) 0;
158 m_backgroundPixel
= -1;
159 m_currentPenWidth
= 1;
160 m_currentPenJoin
= -1;
161 m_currentPenDashCount
= -1;
162 m_currentPenDash
= (wxMOTIFDash
*) NULL
;
165 // m_currentBkMode = wxTRANSPARENT;
166 m_colour
= wxColourDisplay();
167 m_currentRegion
= (WXRegion
) 0;
168 m_userRegion
= (WXRegion
) 0;
172 m_display
= window
->GetXDisplay();
173 m_pixmap
= window
->GetXWindow();
174 Display
* display
= (Display
*) m_display
;
176 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
179 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
180 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
181 gcvalues
.graphics_exposures
= False
;
182 gcvalues
.subwindow_mode
= IncludeInferiors
;
183 gcvalues
.line_width
= 1;
184 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
185 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
188 if (m_window
->GetBackingPixmap())
190 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
191 DefaultScreen (display
)),
192 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
196 m_backgroundPixel
= (int) gcvalues
.background
;
198 // Get the current Font so we can set it back later
200 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
201 m_oldFont
= (WXFont
) valReturn
.font
;
203 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
206 wxWindowDC::~wxWindowDC()
208 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
210 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
212 if (m_window
&& m_window
->GetBackingPixmap())
213 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
217 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
221 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
222 m_gcBacking
= (WXGC
) 0;
225 XDestroyRegion ((Region
) m_currentRegion
);
226 m_currentRegion
= (WXRegion
) 0;
229 XDestroyRegion ((Region
) m_userRegion
);
230 m_userRegion
= (WXRegion
) 0;
233 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
234 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
236 wxFAIL_MSG("not implemented");
239 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
241 // Generic (and therefore rather inefficient) method.
242 // Could be improved.
244 wxBitmap
bitmap(1, 1);
245 memdc
.SelectObject(bitmap
);
246 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
247 memdc
.SelectObject(wxNullBitmap
);
248 wxImage
image(bitmap
);
249 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
253 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
255 wxCHECK_RET( Ok(), "invalid dc" );
257 int x1d
, y1d
, x2d
, y2d
;
259 // FreeGetPixelCache();
269 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
271 if (m_window
&& m_window
->GetBackingPixmap())
272 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
273 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
274 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
276 CalcBoundingBox(x1
, y1
);
277 CalcBoundingBox(x2
, y2
);
280 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
282 wxCHECK_RET( Ok(), "invalid dc" );
287 int xx
= XLOG2DEV (x
);
288 int yy
= YLOG2DEV (y
);
290 wxDisplaySize (&ww
, &hh
);
291 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
293 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
296 if (m_window
&& m_window
->GetBackingPixmap())
300 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
303 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
309 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
311 wxCHECK_RET( Ok(), "invalid dc" );
313 // FreeGetPixelCache();
315 int xx1
= XLOG2DEV (x1
);
316 int yy1
= YLOG2DEV (y1
);
317 int xx2
= XLOG2DEV (x2
);
318 int yy2
= YLOG2DEV (y2
);
319 int xxc
= XLOG2DEV (xc
);
320 int yyc
= YLOG2DEV (yc
);
321 int xxc_2
= XLOG2DEV_2 (xc
);
322 int yyc_2
= YLOG2DEV_2 (yc
);
324 wxCoord dx
= xx1
- xxc
;
325 wxCoord dy
= yy1
- yyc
;
326 double radius
= sqrt (dx
* dx
+ dy
* dy
);
327 wxCoord r
= (wxCoord
) radius
;
329 double radius1
, radius2
;
331 if (xx1
== xx2
&& yy1
== yy2
)
336 else if (radius
== 0.0)
337 radius1
= radius2
= 0.0;
346 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
354 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
358 int alpha1
= (int) radius1
;
359 int alpha2
= (int) (radius2
- radius1
);
362 while (alpha2
> 360 * 64)
365 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
368 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
369 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
371 if (m_window
&& m_window
->GetBackingPixmap())
372 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
373 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
377 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
381 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
382 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
384 if (m_window
&& m_window
->GetBackingPixmap())
385 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
386 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
388 CalcBoundingBox (x1
, y1
);
389 CalcBoundingBox (x2
, y2
);
392 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
394 wxCHECK_RET( Ok(), "invalid dc" );
400 wd
= XLOG2DEVREL(width
);
401 hd
= YLOG2DEVREL(height
);
403 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
404 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
405 int start
= int(sa
*64);
406 int end
= int(ea
*64);
407 if (start
<0) start
+=360*64;
408 if (end
<0) end
+=360*64;
409 if (end
>start
) end
-=start
;
410 else end
+=360*64-start
;
412 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
414 m_autoSetting
= TRUE
; // must be reset
417 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
419 if (m_window
&& m_window
->GetBackingPixmap())
420 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
421 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
424 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
428 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
429 if (m_window
&& m_window
->GetBackingPixmap())
430 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
431 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
433 CalcBoundingBox (x
, y
);
434 CalcBoundingBox (x
+ width
, y
+ height
);
437 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
439 wxCHECK_RET( Ok(), "invalid dc" );
441 // FreeGetPixelCache();
443 if (m_pen
.Ok() && m_autoSetting
)
446 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
447 if (m_window
&& m_window
->GetBackingPixmap())
448 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
450 CalcBoundingBox (x
, y
);
453 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
455 wxCHECK_RET( Ok(), "invalid dc" );
457 // FreeGetPixelCache();
459 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
464 XPoint
*xpoints
= new XPoint
[n
];
467 for (i
= 0; i
< n
; i
++)
469 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
470 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
472 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
474 if (m_window
&& m_window
->GetBackingPixmap())
476 for (i
= 0; i
< n
; i
++)
478 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
479 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
481 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
487 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
488 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
490 wxCHECK_RET( Ok(), "invalid dc" );
492 // FreeGetPixelCache();
494 XPoint
*xpoints1
= new XPoint
[n
+ 1];
495 XPoint
*xpoints2
= new XPoint
[n
+ 1];
497 for (i
= 0; i
< n
; i
++)
499 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
500 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
501 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
502 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
503 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
506 // Close figure for XDrawLines (not needed for XFillPolygon)
507 xpoints1
[i
].x
= xpoints1
[0].x
;
508 xpoints1
[i
].y
= xpoints1
[0].y
;
509 xpoints2
[i
].x
= xpoints2
[0].x
;
510 xpoints2
[i
].y
= xpoints2
[0].y
;
512 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
515 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
516 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
517 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
518 if (m_window
&& m_window
->GetBackingPixmap())
520 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
521 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
522 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
523 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
527 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
531 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
533 if (m_window
&& m_window
->GetBackingPixmap())
534 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
541 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
543 wxCHECK_RET( Ok(), "invalid dc" );
545 // FreeGetPixelCache();
547 int xd
, yd
, wfd
, hfd
, wd
, hd
;
551 wfd
= XLOG2DEVREL(width
);
553 hfd
= YLOG2DEVREL(height
);
556 if (wfd
== 0 || hfd
== 0) return;
557 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
558 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
560 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
563 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
565 if (m_window
&& m_window
->GetBackingPixmap())
566 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
567 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
571 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
575 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
577 if (m_window
&& m_window
->GetBackingPixmap())
578 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
579 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
582 CalcBoundingBox (x
, y
);
583 CalcBoundingBox (x
+ width
, y
+ height
);
586 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
588 wxCHECK_RET( Ok(), "invalid dc" );
590 // FreeGetPixelCache();
592 // If radius is negative, it's a proportion of the smaller dimension.
594 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
596 int xd
= XLOG2DEV (x
);
597 int yd
= YLOG2DEV (y
);
598 int rd
= XLOG2DEVREL ((long) radius
);
599 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
600 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
605 // If radius is zero use DrawRectangle() instead to avoid
606 // X drawing errors with small radii
609 DrawRectangle( x
, y
, width
, height
);
613 // Draw nothing if transformed w or h is 0
614 if (wd
== 0 || hd
== 0) return;
616 // CMB: adjust size if outline is drawn otherwise the result is
617 // 1 pixel too wide and high
618 if (m_pen
.GetStyle() != wxTRANSPARENT
)
624 // CMB: ensure dd is not larger than rectangle otherwise we
625 // get an hour glass shape
626 if (rw_d
> wd
) rw_d
= wd
;
627 if (rw_d
> hd
) rw_d
= hd
;
630 // For backing pixmap
631 int xd2
= XLOG2DEV_2 (x
);
632 int yd2
= YLOG2DEV_2 (y
);
633 int rd2
= XLOG2DEVREL ((long) radius
);
634 int wd2
= XLOG2DEVREL (width
) ;
635 int hd2
= YLOG2DEVREL (height
) ;
640 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
644 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
646 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
649 // Arcs start from 3 o'clock, positive angles anticlockwise
651 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
652 rw_d
, rh_d
, 90 * 64, 90 * 64);
654 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
655 // rw_d, rh_d, 0, 90 * 64);
656 rw_d
, rh_d
, 0, 91 * 64);
658 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
660 // rw_d, rh_d, 270 * 64, 90 * 64);
661 rw_d
, rh_d
, 269 * 64, 92 * 64);
663 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
664 rw_d
, rh_d
, 180 * 64, 90 * 64);
666 if (m_window
&& m_window
->GetBackingPixmap())
668 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
669 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
670 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
671 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
673 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
674 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
675 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
676 xd2
+ wd2
- rw_d2
, yd2
,
677 // rw_d2, rh_d2, 0, 90 * 64);
678 rw_d2
, rh_d2
, 0, 91 * 64);
679 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
682 // rw_d2, rh_d2, 270 * 64, 90 * 64);
683 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
684 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
685 xd2
, yd2
+ hd2
- rh_d2
,
686 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
690 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
693 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
694 xd
+ wd
- rd
+ 1, yd
);
695 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
696 xd
+ wd
- rd
, yd
+ hd
);
698 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
700 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
701 xd
+ wd
, yd
+ hd
- rd
+ 1);
702 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
703 rw_d
, rh_d
, 90 * 64, 90 * 64);
704 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
705 // rw_d, rh_d, 0, 90 * 64);
706 rw_d
, rh_d
, 0, 91 * 64);
707 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
709 rw_d
, rh_d
, 269 * 64, 92 * 64);
710 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
711 rw_d
, rh_d
, 180 * 64, 90 * 64);
713 if (m_window
&& m_window
->GetBackingPixmap())
715 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
717 xd2
+ wd2
- rd2
+ 1, yd2
);
718 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
719 xd2
+ rd2
, yd2
+ hd2
,
720 xd2
+ wd2
- rd2
, yd2
+ hd2
);
722 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
724 xd2
, yd2
+ hd2
- rd2
);
725 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
726 xd2
+ wd2
, yd2
+ rd2
,
727 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
728 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
730 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
731 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
732 xd2
+ wd2
- rw_d2
, yd2
,
733 // rw_d2, rh_d2, 0, 90 * 64);
734 rw_d2
, rh_d2
, 0, 91 * 64);
735 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
738 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
739 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
740 xd2
, yd2
+ hd2
- rh_d2
,
741 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
744 CalcBoundingBox (x
, y
);
745 CalcBoundingBox (x
+ width
, y
+ height
);
750 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
752 wxCHECK_RET( Ok(), "invalid dc" );
754 // Check for negative width and height
767 // FreeGetPixelCache();
769 static const int angle
= 23040;
775 wd
= XLOG2DEVREL(width
) ;
776 hd
= YLOG2DEVREL(height
) ;
778 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
781 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
782 if (m_window
&& m_window
->GetBackingPixmap())
783 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
784 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
785 XLOG2DEVREL (width
) - WX_GC_CF
,
786 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
789 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
793 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
794 if (m_window
&& m_window
->GetBackingPixmap())
795 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
796 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
797 XLOG2DEVREL (width
) - WX_GC_CF
,
798 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
800 CalcBoundingBox (x
, y
);
801 CalcBoundingBox (x
+ width
, y
+ height
);
805 bool wxWindowDC::CanDrawBitmap() const
807 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
813 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
815 // FreeGetPixelCache();
817 // Be sure that foreground pixels (1) of
818 // the Icon will be painted with pen colour. [m_pen.SetColour()]
819 // Background pixels (0) will be painted with
820 // last selected background color. [::SetBackground]
821 if (m_pen
.Ok() && m_autoSetting
)
825 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
826 width
= icon
.GetWidth();
827 height
= icon
.GetHeight();
828 if (icon
.GetDisplay() == m_display
)
830 if (icon
.GetDepth() <= 1)
832 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
834 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
838 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
840 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
844 if (m_window
&& m_window
->GetBackingPixmap())
846 if (icon
.GetDepth() <= 1)
848 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
849 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
853 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
855 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
858 } else { /* Remote copy (different (Display*) m_displays) */
859 XImage
*cache
= NULL
;
860 if (m_window
&& m_window
->GetBackingPixmap())
861 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
862 (GC
) m_gcBacking
, 0, 0, width
, height
,
863 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
864 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
866 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
868 CalcBoundingBox (x
, y
);
872 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
873 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
874 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
876 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
878 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
880 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
882 // FreeGetPixelCache();
884 // Be sure that foreground pixels (1) of the Icon will be painted with pen
885 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
886 // last selected background color. [::SetBackground]
887 if (m_pen
.Ok() && m_autoSetting
)
890 // Do bitmap scaling if necessary
892 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
893 Pixmap sourcePixmap
= (Pixmap
) NULL
;
894 double scaleX
, scaleY
;
895 GetUserScale(& scaleX
, & scaleY
);
897 // Sorry, can't scale masks just yet
898 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
900 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
901 wxBitmap
& bitmap
= memDC
->GetBitmap();
903 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
905 wxImage
image(bitmap
);
908 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
912 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
913 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
915 image
= image
.Scale(scaledW
, scaledH
);
916 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
917 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
921 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
923 if (m_pixmap
&& sourcePixmap
)
926 int orig
= m_logicalFunction
;
928 SetLogicalFunction (rop
);
930 if (m_display
!= sourceDC
->m_display
)
932 XImage
*cache
= NULL
;
934 if (m_window
&& m_window
->GetBackingPixmap())
935 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
936 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
938 source
->LogicalToDeviceX (xsrc
),
939 source
->LogicalToDeviceY (ysrc
),
940 source
->LogicalToDeviceXRel(width
),
941 source
->LogicalToDeviceYRel(height
),
942 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
945 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
947 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
948 wxBitmap
& sel
= memDC
->GetBitmap();
949 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
951 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
952 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
956 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
957 source
->LogicalToDeviceX (xsrc
),
958 source
->LogicalToDeviceY (ysrc
),
959 source
->LogicalToDeviceXRel(width
),
960 source
->LogicalToDeviceYRel(height
),
961 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
966 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
967 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
972 if (m_window
&& m_window
->GetBackingPixmap())
974 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
975 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
977 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
978 source
->LogicalToDeviceX (xsrc
),
979 source
->LogicalToDeviceY (ysrc
),
980 source
->LogicalToDeviceXRel(width
),
981 source
->LogicalToDeviceYRel(height
),
982 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
986 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
987 source
->LogicalToDeviceX (xsrc
),
988 source
->LogicalToDeviceY (ysrc
),
989 source
->LogicalToDeviceXRel(width
),
990 source
->LogicalToDeviceYRel(height
),
991 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
994 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
996 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
997 wxBitmap
& sel
= memDC
->GetBitmap();
998 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
1000 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
1001 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1005 // Check if we're copying from a mono bitmap
1006 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1007 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1009 XCopyPlane ((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
), 1);
1018 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1019 source
->LogicalToDeviceX (xsrc
),
1020 source
->LogicalToDeviceY (ysrc
),
1021 source
->LogicalToDeviceXRel(width
),
1022 source
->LogicalToDeviceYRel(height
),
1023 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1028 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1029 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1032 } /* Remote/local (Display*) m_display */
1033 CalcBoundingBox (xdest
, ydest
);
1034 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1036 SetLogicalFunction(orig
);
1038 if (scaledBitmap
) delete scaledBitmap
;
1042 if (scaledBitmap
) delete scaledBitmap
;
1047 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1049 wxCHECK_RET( Ok(), "invalid dc" );
1051 // Since X draws from the baseline of the text, must add the text height
1057 slen
= strlen(text
);
1061 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1062 int direction
, descent
;
1063 XCharStruct overall_return
;
1066 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1067 &ascent
, &descent
, &overall_return
);
1070 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1071 &ascent
, &descent
, &overall_return
);
1073 cx
= overall_return
.width
;
1074 cy
= ascent
+ descent
;
1077 // First draw a rectangle representing the text background, if a text
1078 // background is specified
1079 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1081 wxColour oldPenColour
= m_currentColour
;
1082 m_currentColour
= m_textBackgroundColour
;
1083 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1084 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1085 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1086 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1088 // This separation of the big && test required for gcc2.7/HP UX 9.02
1089 // or pixel value can be corrupted!
1090 sameColour
= (sameColour
&&
1091 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1093 if (!sameColour
|| !GetOptimization())
1095 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1096 m_currentColour
= m_textBackgroundColour
;
1098 // Set the GC to the required colour
1101 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1102 if (m_window
&& m_window
->GetBackingPixmap())
1103 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1107 m_textBackgroundColour
= oldPenColour
;
1109 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1110 if (m_window
&& m_window
->GetBackingPixmap())
1111 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1112 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1115 // Now set the text foreground and draw the text
1116 if (m_textForegroundColour
.Ok ())
1118 wxColour oldPenColour
= m_currentColour
;
1119 m_currentColour
= m_textForegroundColour
;
1120 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1121 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1122 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1123 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1124 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1126 if (!sameColour
|| !GetOptimization())
1129 if (!m_colour
) // Mono display
1131 // Unless foreground is really white, draw it in black
1132 unsigned char red
= m_textForegroundColour
.Red ();
1133 unsigned char blue
= m_textForegroundColour
.Blue ();
1134 unsigned char green
= m_textForegroundColour
.Green ();
1135 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1136 && green
== (unsigned char) 255)
1138 m_currentColour
= *wxWHITE
;
1139 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1140 m_currentColour
.SetPixel(pixel
);
1141 m_textForegroundColour
.SetPixel(pixel
);
1145 m_currentColour
= *wxBLACK
;
1146 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1147 m_currentColour
.SetPixel(pixel
);
1148 m_textForegroundColour
.SetPixel(pixel
);
1153 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1154 m_currentColour
.SetPixel(pixel
);
1157 // Set the GC to the required colour
1160 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1161 if (m_window
&& m_window
->GetBackingPixmap())
1162 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1166 m_textForegroundColour
= oldPenColour
;
1169 // We need to add the ascent, not the whole height, since X draws at the
1170 // point above the descender.
1173 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1174 (XChar2b
*)(char*) (const char*) text
, slen
);
1177 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1179 if (m_window
&& m_window
->GetBackingPixmap()) {
1182 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1183 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1184 (XChar2b
*)(char*) (const char*) text
, slen
);
1187 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1188 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1192 GetTextExtent (text
, &w
, &h
);
1193 CalcBoundingBox (x
+ w
, y
+ h
);
1194 CalcBoundingBox (x
, y
);
1197 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1201 DrawText(text
, x
, y
);
1205 wxCHECK_RET( Ok(), "invalid dc" );
1207 // Since X draws from the baseline of the text, must add the text height
1213 slen
= strlen(text
);
1217 // Calculate text extent.
1218 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1219 int direction
, descent
;
1220 XCharStruct overall_return
;
1223 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1224 &ascent
, &descent
, &overall_return
);
1227 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1228 &ascent
, &descent
, &overall_return
);
1230 cx
= overall_return
.width
;
1231 cy
= ascent
+ descent
;
1234 wxBitmap
src(cx
, cy
);
1236 dc
.SelectObject(src
);
1237 dc
.SetFont(GetFont());
1238 dc
.SetBackground(*wxWHITE_BRUSH
);
1239 dc
.SetBrush(*wxBLACK_BRUSH
);
1241 dc
.DrawText(text
, 0, 0);
1242 dc
.SetFont(wxNullFont
);
1244 // Calculate the size of the rotated bounding box.
1245 double dx
= cos(angle
/ 180.0 * M_PI
);
1246 double dy
= sin(angle
/ 180.0 * M_PI
);
1247 double x4
= -cy
* dy
;
1248 double y4
= cy
* dx
;
1249 double x3
= cx
* dx
;
1250 double y3
= cx
* dy
;
1251 double x2
= x3
+ x4
;
1252 double y2
= y3
+ y4
;
1256 // Create image from the source bitmap after writing the text into it.
1259 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1260 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1261 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1262 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1264 // This rotates counterclockwise around the top left corner.
1265 for (int rx
= minx
; rx
< maxx
; rx
++)
1267 for (int ry
= miny
; ry
< maxy
; ry
++)
1269 // transform dest coords to source coords
1270 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1271 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1272 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1274 // draw black pixels, ignore white ones (i.e. transparent b/g)
1275 if (image
.GetRed(sx
, sy
) == 0)
1277 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1282 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1289 // First draw a rectangle representing the text background, if a text
1290 // background is specified
1291 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1293 wxColour oldPenColour
= m_currentColour
;
1294 m_currentColour
= m_textBackgroundColour
;
1295 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1296 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1297 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1298 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1300 // This separation of the big && test required for gcc2.7/HP UX 9.02
1301 // or pixel value can be corrupted!
1302 sameColour
= (sameColour
&&
1303 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1305 if (!sameColour
|| !GetOptimization())
1307 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1308 m_currentColour
= m_textBackgroundColour
;
1310 // Set the GC to the required colour
1313 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1314 if (m_window
&& m_window
->GetBackingPixmap())
1315 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1319 m_textBackgroundColour
= oldPenColour
;
1321 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1322 if (m_window
&& m_window
->GetBackingPixmap())
1323 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1324 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1329 // XXX use pixmap size
1330 GetTextExtent (text
, &w
, &h
);
1331 CalcBoundingBox (x
+ w
, y
+ h
);
1332 CalcBoundingBox (x
, y
);
1335 bool wxWindowDC::CanGetTextExtent() const
1340 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1341 wxCoord
*descent
, wxCoord
*externalLeading
,
1342 wxFont
*font
) const
1344 wxCHECK_RET( Ok(), "invalid dc" );
1346 wxFont
* theFont
= font
;
1348 theFont
= (wxFont
*)&m_font
; // const_cast
1352 // TODO: this should be an error log function
1353 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1355 if (width
) *width
= -1;
1356 if (height
) *height
= -1;
1360 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1362 int direction
, ascent
, descent2
;
1363 XCharStruct overall
;
1368 slen
= str16len(string
);
1371 slen
= strlen(string
);
1375 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1376 &ascent
, &descent2
, &overall
);
1379 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1380 &ascent
, &descent2
, &overall
);
1382 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1383 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1385 *descent
= descent2
;
1386 if (externalLeading
)
1387 *externalLeading
= 0;
1390 wxCoord
wxWindowDC::GetCharWidth() const
1392 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1393 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1395 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1397 int direction
, ascent
, descent
;
1398 XCharStruct overall
;
1399 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1400 &descent
, &overall
);
1401 return XDEV2LOGREL(overall
.width
);
1404 wxCoord
wxWindowDC::GetCharHeight() const
1406 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1407 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1409 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1411 int direction
, ascent
, descent
;
1412 XCharStruct overall
;
1413 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1414 &descent
, &overall
);
1415 // return XDEV2LOGREL(overall.ascent + overall.descent);
1416 return XDEV2LOGREL(ascent
+ descent
);
1419 void wxWindowDC::Clear()
1421 wxCHECK_RET( Ok(), "invalid dc" );
1426 m_window
->GetSize(&w
, &h
);
1428 if (m_window
&& m_window
->GetBackingPixmap())
1430 w
= m_window
->GetPixmapWidth();
1431 h
= m_window
->GetPixmapHeight();
1436 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1438 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1439 w
= memDC
->GetBitmap().GetWidth();
1440 h
= memDC
->GetBitmap().GetHeight();
1446 wxBrush saveBrush
= m_brush
;
1447 SetBrush (m_backgroundBrush
);
1449 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1451 if (m_window
&& m_window
->GetBackingPixmap())
1452 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1454 m_brush
= saveBrush
;
1457 void wxWindowDC::Clear(const wxRect
& rect
)
1459 wxCHECK_RET( Ok(), "invalid dc" );
1461 int x
= rect
.x
; int y
= rect
.y
;
1462 int w
= rect
.width
; int h
= rect
.height
;
1464 wxBrush saveBrush
= m_brush
;
1465 SetBrush (m_backgroundBrush
);
1467 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1469 if (m_window
&& m_window
->GetBackingPixmap())
1470 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1472 m_brush
= saveBrush
;
1475 void wxWindowDC::SetFont( const wxFont
&font
)
1477 wxCHECK_RET( Ok(), "invalid dc" );
1483 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1485 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1487 if (m_window
&& m_window
->GetBackingPixmap())
1488 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1493 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1495 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1496 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1498 if (m_window
&& m_window
->GetBackingPixmap())
1499 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1502 void wxWindowDC::SetPen( const wxPen
&pen
)
1504 wxCHECK_RET( Ok(), "invalid dc" );
1510 wxBitmap oldStipple
= m_currentStipple
;
1511 int oldStyle
= m_currentStyle
;
1512 int oldFill
= m_currentFill
;
1513 int old_pen_width
= m_currentPenWidth
;
1514 int old_pen_join
= m_currentPenJoin
;
1515 int old_pen_cap
= m_currentPenCap
;
1516 int old_pen_nb_dash
= m_currentPenDashCount
;
1517 wxMOTIFDash
*old_pen_dash
= m_currentPenDash
;
1519 wxColour oldPenColour
= m_currentColour
;
1520 m_currentColour
= m_pen
.GetColour ();
1521 m_currentStyle
= m_pen
.GetStyle ();
1522 m_currentFill
= m_pen
.GetStyle (); // TODO?
1523 m_currentPenWidth
= m_pen
.GetWidth ();
1524 m_currentPenJoin
= m_pen
.GetJoin ();
1525 m_currentPenCap
= m_pen
.GetCap ();
1526 m_currentPenDashCount
= m_pen
.GetDashCount();
1527 m_currentPenDash
= (wxMOTIFDash
*)m_pen
.GetDash();
1529 if (m_currentStyle
== wxSTIPPLE
)
1530 m_currentStipple
= * m_pen
.GetStipple ();
1532 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1533 oldFill
== m_currentFill
&&
1534 old_pen_join
== m_currentPenJoin
&&
1535 old_pen_cap
== m_currentPenCap
&&
1536 old_pen_nb_dash
== m_currentPenDashCount
&&
1537 old_pen_dash
== m_currentPenDash
&&
1538 old_pen_width
== m_currentPenWidth
);
1540 bool sameColour
= (oldPenColour
.Ok () &&
1541 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1542 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1543 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1544 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1546 if (!sameStyle
|| !GetOptimization())
1548 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1549 if (scaled_width
< 0)
1555 static const wxMOTIFDash dotted
[] = {2, 5};
1556 static const wxMOTIFDash short_dashed
[] = {4, 4};
1557 static const wxMOTIFDash long_dashed
[] = {4, 8};
1558 static const wxMOTIFDash dotted_dashed
[] = {6, 6, 2, 6};
1560 // We express dash pattern in pen width unit, so we are
1561 // independent of zoom factor and so on...
1563 const wxMOTIFDash
*req_dash
;
1565 switch (m_pen
.GetStyle ())
1568 req_nb_dash
= m_currentPenDashCount
;
1569 req_dash
= m_currentPenDash
;
1570 style
= LineOnOffDash
;
1575 style
= LineOnOffDash
;
1579 req_dash
= short_dashed
;
1580 style
= LineOnOffDash
;
1584 req_dash
= long_dashed
;
1585 style
= LineOnOffDash
;
1589 req_dash
= dotted_dashed
;
1590 style
= LineOnOffDash
;
1597 req_dash
= (wxMOTIFDash
*)NULL
;
1601 if (req_dash
&& req_nb_dash
)
1603 wxMOTIFDash
*real_req_dash
= new wxMOTIFDash
[req_nb_dash
];
1606 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1607 for (int i
= 0; i
< req_nb_dash
; i
++)
1608 real_req_dash
[i
] = req_dash
[i
] * factor
;
1609 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1611 if (m_window
&& m_window
->GetBackingPixmap())
1612 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1613 delete[]real_req_dash
;
1617 // No Memory. We use non-scaled dash pattern...
1618 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1620 if (m_window
&& m_window
->GetBackingPixmap())
1621 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1625 switch (m_pen
.GetCap ())
1627 case wxCAP_PROJECTING
:
1628 cap
= CapProjecting
;
1635 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1639 switch (m_pen
.GetJoin ())
1653 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1655 if (m_window
&& m_window
->GetBackingPixmap())
1656 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1659 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1663 oldStipple
= wxNullBitmap
; // For later reset!!
1665 switch (m_currentFill
)
1667 case wxBDIAGONAL_HATCH
:
1668 if (bdiag
== (Pixmap
) 0)
1669 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1670 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1671 bdiag_bits
, bdiag_width
, bdiag_height
);
1674 case wxFDIAGONAL_HATCH
:
1675 if (fdiag
== (Pixmap
) 0)
1676 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1677 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1678 fdiag_bits
, fdiag_width
, fdiag_height
);
1682 if (cross
== (Pixmap
) 0)
1683 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1684 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1685 cross_bits
, cross_width
, cross_height
);
1688 case wxHORIZONTAL_HATCH
:
1689 if (horiz
== (Pixmap
) 0)
1690 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1691 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1692 horiz_bits
, horiz_width
, horiz_height
);
1695 case wxVERTICAL_HATCH
:
1696 if (verti
== (Pixmap
) 0)
1697 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1698 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1699 verti_bits
, verti_width
, verti_height
);
1702 case wxCROSSDIAG_HATCH
:
1704 if (cdiag
== (Pixmap
) 0)
1705 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1706 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1707 cdiag_bits
, cdiag_width
, cdiag_height
);
1711 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1713 if (m_window
&& m_window
->GetBackingPixmap())
1714 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1716 else if (m_currentStipple
.Ok()
1717 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1719 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1721 if (m_window
&& m_window
->GetBackingPixmap())
1722 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1725 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1729 if (m_currentFill
== wxSTIPPLE
)
1730 fill_style
= FillStippled
;
1731 else if (IS_HATCH (m_currentFill
))
1732 fill_style
= FillStippled
;
1734 fill_style
= FillSolid
;
1735 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1736 if (m_window
&& m_window
->GetBackingPixmap())
1737 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1740 // must test m_logicalFunction, because it involves background!
1741 if (!sameColour
|| !GetOptimization()
1742 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1745 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1746 pixel
= m_backgroundPixel
;
1749 unsigned char red
= m_pen
.GetColour ().Red ();
1750 unsigned char blue
= m_pen
.GetColour ().Blue ();
1751 unsigned char green
= m_pen
.GetColour ().Green ();
1752 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1753 && green
== (unsigned char) 255)
1755 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1756 m_currentColour
= *wxWHITE
;
1757 m_pen
.GetColour().SetPixel(pixel
);
1758 m_currentColour
.SetPixel(pixel
);
1762 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1763 m_currentColour
= *wxBLACK
;
1764 m_pen
.GetColour().SetPixel(pixel
);
1769 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1770 m_currentColour
.SetPixel(pixel
);
1773 // Finally, set the GC to the required colour
1776 if (m_logicalFunction
== wxXOR
)
1779 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1780 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1781 if (m_window
&& m_window
->GetBackingPixmap())
1782 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1786 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1787 if (m_window
&& m_window
->GetBackingPixmap())
1788 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1793 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1798 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1800 wxCHECK_RET( Ok(), "invalid dc" );
1804 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1807 int oldFill
= m_currentFill
;
1808 wxBitmap oldStipple
= m_currentStipple
;
1810 m_autoSetting
|= 0x1;
1812 m_currentFill
= m_brush
.GetStyle ();
1813 if (m_currentFill
== wxSTIPPLE
)
1814 m_currentStipple
= * m_brush
.GetStipple ();
1816 wxColour
oldBrushColour(m_currentColour
);
1817 m_currentColour
= m_brush
.GetColour ();
1819 bool sameColour
= (oldBrushColour
.Ok () &&
1820 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1821 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1822 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1823 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1825 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1827 switch (brush
.GetStyle ())
1831 case wxBDIAGONAL_HATCH
:
1832 case wxCROSSDIAG_HATCH
:
1833 case wxFDIAGONAL_HATCH
:
1835 case wxHORIZONTAL_HATCH
:
1836 case wxVERTICAL_HATCH
:
1839 // Chris Breeze 23/07/97: use background mode to determine whether
1840 // fill style should be solid or transparent
1841 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1842 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1843 if (m_window
&& m_window
->GetBackingPixmap())
1844 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1849 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1850 if (m_window
&& m_window
->GetBackingPixmap())
1851 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1855 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1859 switch (m_currentFill
)
1861 case wxBDIAGONAL_HATCH
:
1862 if (bdiag
== (Pixmap
) 0)
1863 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1864 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1865 bdiag_bits
, bdiag_width
, bdiag_height
);
1868 case wxFDIAGONAL_HATCH
:
1869 if (fdiag
== (Pixmap
) 0)
1870 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1871 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1872 fdiag_bits
, fdiag_width
, fdiag_height
);
1876 if (cross
== (Pixmap
) 0)
1877 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1878 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1879 cross_bits
, cross_width
, cross_height
);
1882 case wxHORIZONTAL_HATCH
:
1883 if (horiz
== (Pixmap
) 0)
1884 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1885 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1886 horiz_bits
, horiz_width
, horiz_height
);
1889 case wxVERTICAL_HATCH
:
1890 if (verti
== (Pixmap
) 0)
1891 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1892 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1893 verti_bits
, verti_width
, verti_height
);
1896 case wxCROSSDIAG_HATCH
:
1898 if (cdiag
== (Pixmap
) 0)
1899 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1900 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1901 cdiag_bits
, cdiag_width
, cdiag_height
);
1905 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1907 if (m_window
&& m_window
->GetBackingPixmap())
1908 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1910 // X can forget the stipple value when resizing a window (apparently)
1911 // so always set the stipple.
1912 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1914 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1915 if (m_window
&& m_window
->GetBackingPixmap())
1916 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1919 // must test m_logicalFunction, because it involves background!
1920 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1925 // Policy - on a monochrome screen, all brushes are white,
1926 // except when they're REALLY black!!!
1927 unsigned char red
= m_brush
.GetColour ().Red ();
1928 unsigned char blue
= m_brush
.GetColour ().Blue ();
1929 unsigned char green
= m_brush
.GetColour ().Green ();
1931 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1932 && green
== (unsigned char) 0)
1934 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1935 m_currentColour
= *wxBLACK
;
1936 m_brush
.GetColour().SetPixel(pixel
);
1937 m_currentColour
.SetPixel(pixel
);
1941 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1942 m_currentColour
= *wxWHITE
;
1943 m_brush
.GetColour().SetPixel(pixel
);
1944 m_currentColour
.SetPixel(pixel
);
1947 // N.B. comment out the above line and uncomment the following lines
1948 // if you want non-white colours to be black on a monochrome display.
1950 if (red == (unsigned char )255 && blue == (unsigned char)255
1951 && green == (unsigned char)255)
1952 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1954 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1957 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1959 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1960 m_currentColour
.SetPixel(pixel
);
1964 // Finally, set the GC to the required colour
1965 if (m_logicalFunction
== wxXOR
)
1968 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1969 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1970 if (m_window
&& m_window
->GetBackingPixmap())
1971 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1975 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1976 if (m_window
&& m_window
->GetBackingPixmap())
1977 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1982 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1985 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1987 wxCHECK_RET( Ok(), "invalid dc" );
1989 m_backgroundBrush
= brush
;
1991 if (!m_backgroundBrush
.Ok())
1994 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1996 // New behaviour, 10/2/99: setting the background brush of a DC
1997 // doesn't affect the window background colour.
1999 // XSetWindowBackground doesn't work for non-Window pixmaps
2000 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2001 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2004 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2005 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2006 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2007 if (m_window
&& m_window
->GetBackingPixmap())
2008 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2011 void wxWindowDC::SetLogicalFunction( int function
)
2013 wxCHECK_RET( Ok(), "invalid dc" );
2018 if (m_logicalFunction
== function
)
2024 x_function
= GXclear
;
2030 x_function
= GXinvert
;
2033 x_function
= GXorReverse
;
2036 x_function
= GXandReverse
;
2045 x_function
= GXandInverted
;
2048 x_function
= GXnoop
;
2054 x_function
= GXequiv
;
2057 x_function
= GXcopyInverted
;
2060 x_function
= GXorInverted
;
2063 x_function
= GXnand
;
2070 x_function
= GXcopy
;
2074 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2075 if (m_window
&& m_window
->GetBackingPixmap())
2076 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2078 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2079 /* MATTHEW: [9] Need to redo pen simply */
2080 m_autoSetting
|= 0x2;
2082 m_logicalFunction
= function
;
2086 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2088 wxCHECK_RET( Ok(), "invalid dc" );
2090 if (m_textForegroundColour
== col
)
2093 m_textForegroundColour
= col
;
2097 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2099 wxCHECK_RET( Ok(), "invalid dc" );
2101 if (m_textBackgroundColour
== col
)
2104 m_textBackgroundColour
= col
;
2105 if (!m_textBackgroundColour
.Ok())
2109 void wxWindowDC::SetBackgroundMode( int mode
)
2111 m_backgroundMode
= mode
;
2114 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2119 /* Use GetXColormap */
2120 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2121 (Colormap
) palette
.GetXColormap());
2123 /* Use wxGetMainColormap */
2124 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2125 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2130 void wxWindowDC::SetDCClipping()
2132 // m_userRegion is the region set by calling SetClippingRegion
2134 if (m_currentRegion
)
2135 XDestroyRegion ((Region
) m_currentRegion
);
2137 // We need to take into account
2138 // clipping imposed on a window by a repaint.
2139 // We'll combine it with the user region. But for now,
2140 // just use the currently-defined user clipping region.
2141 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2142 m_currentRegion
= (WXRegion
) XCreateRegion ();
2144 m_currentRegion
= (WXRegion
) NULL
;
2146 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2147 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2148 else if (m_userRegion
)
2149 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2150 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2151 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2152 (Region
) m_currentRegion
);
2154 if (m_currentRegion
)
2156 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2160 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2165 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2167 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2170 XDestroyRegion ((Region
) m_userRegion
);
2171 m_userRegion
= (WXRegion
) XCreateRegion ();
2175 r
.width
= XLOG2DEVREL(width
);
2176 r
.height
= YLOG2DEVREL(height
);
2177 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2181 // Needs to work differently for Pixmap: without this,
2182 // there's a nasty (Display*) m_display bug. 8/12/94
2183 if (m_window
&& m_window
->GetBackingPixmap())
2185 XRectangle rects
[1];
2186 rects
[0].x
= XLOG2DEV_2(x
);
2187 rects
[0].y
= YLOG2DEV_2(y
);
2188 rects
[0].width
= XLOG2DEVREL(width
);
2189 rects
[0].height
= YLOG2DEVREL(height
);
2190 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2194 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2196 wxRect box
= region
.GetBox();
2198 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2201 XDestroyRegion ((Region
) m_userRegion
);
2202 m_userRegion
= (WXRegion
) XCreateRegion ();
2204 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2208 // Needs to work differently for Pixmap: without this,
2209 // there's a nasty (Display*) m_display bug. 8/12/94
2210 if (m_window
&& m_window
->GetBackingPixmap())
2212 XRectangle rects
[1];
2213 rects
[0].x
= XLOG2DEV_2(box
.x
);
2214 rects
[0].y
= YLOG2DEV_2(box
.y
);
2215 rects
[0].width
= XLOG2DEVREL(box
.width
);
2216 rects
[0].height
= YLOG2DEVREL(box
.height
);
2217 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2222 void wxWindowDC::DestroyClippingRegion()
2224 wxDC::DestroyClippingRegion();
2227 XDestroyRegion ((Region
) m_userRegion
);
2228 m_userRegion
= NULL
;
2233 gc_val
.clip_mask
= None
;
2234 if (m_window
&& m_window
->GetBackingPixmap())
2235 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2238 // Resolution in pixels per logical inch
2239 wxSize
wxWindowDC::GetPPI() const
2241 return wxSize(100, 100);
2244 int wxWindowDC::GetDepth() const
2251 // ----------------------------------- spline code ----------------------------------------
2253 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2254 double a3
, double b3
, double a4
, double b4
);
2255 void wx_clear_stack();
2256 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2257 double *y3
, double *x4
, double *y4
);
2258 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2259 double x4
, double y4
);
2260 static bool wx_spline_add_point(double x
, double y
);
2261 static void wx_spline_draw_point_array(wxDC
*dc
);
2263 wxList wx_spline_point_list
;
2265 #define half(z1, z2) ((z1+z2)/2.0)
2268 /* iterative version */
2270 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2273 register double xmid
, ymid
;
2274 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2277 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2279 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2280 xmid
= (double)half(x2
, x3
);
2281 ymid
= (double)half(y2
, y3
);
2282 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2283 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2284 wx_spline_add_point( x1
, y1
);
2285 wx_spline_add_point( xmid
, ymid
);
2287 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2288 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2289 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2290 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2295 /* utilities used by spline drawing routines */
2297 typedef struct wx_spline_stack_struct
{
2298 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2301 #define SPLINE_STACK_DEPTH 20
2302 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2303 static Stack
*wx_stack_top
;
2304 static int wx_stack_count
;
2306 void wx_clear_stack()
2308 wx_stack_top
= wx_spline_stack
;
2312 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2314 wx_stack_top
->x1
= x1
;
2315 wx_stack_top
->y1
= y1
;
2316 wx_stack_top
->x2
= x2
;
2317 wx_stack_top
->y2
= y2
;
2318 wx_stack_top
->x3
= x3
;
2319 wx_stack_top
->y3
= y3
;
2320 wx_stack_top
->x4
= x4
;
2321 wx_stack_top
->y4
= y4
;
2326 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2327 double *x3
, double *y3
, double *x4
, double *y4
)
2329 if (wx_stack_count
== 0)
2333 *x1
= wx_stack_top
->x1
;
2334 *y1
= wx_stack_top
->y1
;
2335 *x2
= wx_stack_top
->x2
;
2336 *y2
= wx_stack_top
->y2
;
2337 *x3
= wx_stack_top
->x3
;
2338 *y3
= wx_stack_top
->y3
;
2339 *x4
= wx_stack_top
->x4
;
2340 *y4
= wx_stack_top
->y4
;
2344 static bool wx_spline_add_point(double x
, double y
)
2346 wxPoint
*point
= new wxPoint
;
2349 wx_spline_point_list
.Append((wxObject
*)point
);
2353 static void wx_spline_draw_point_array(wxDC
*dc
)
2355 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2356 wxNode
*node
= wx_spline_point_list
.First();
2359 wxPoint
*point
= (wxPoint
*)node
->Data();
2362 node
= wx_spline_point_list
.First();
2366 void wxWindowDC::DoDrawSpline( wxList
*points
)
2368 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2371 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2372 double x1
, y1
, x2
, y2
;
2374 wxNode
*node
= points
->First();
2375 p
= (wxPoint
*)node
->Data();
2380 node
= node
->Next();
2381 p
= (wxPoint
*)node
->Data();
2385 cx1
= (double)((x1
+ x2
) / 2);
2386 cy1
= (double)((y1
+ y2
) / 2);
2387 cx2
= (double)((cx1
+ x2
) / 2);
2388 cy2
= (double)((cy1
+ y2
) / 2);
2390 wx_spline_add_point(x1
, y1
);
2392 while ((node
= node
->Next()) != NULL
)
2394 p
= (wxPoint
*)node
->Data();
2399 cx4
= (double)(x1
+ x2
) / 2;
2400 cy4
= (double)(y1
+ y2
) / 2;
2401 cx3
= (double)(x1
+ cx4
) / 2;
2402 cy3
= (double)(y1
+ cy4
) / 2;
2404 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2408 cx2
= (double)(cx1
+ x2
) / 2;
2409 cy2
= (double)(cy1
+ y2
) / 2;
2412 wx_spline_add_point( cx1
, cy1
);
2413 wx_spline_add_point( x2
, y2
);
2415 wx_spline_draw_point_array( this );
2418 #endif // wxUSE_SPLINE
2422 // ----------------------------------------------------------------------------
2424 // ----------------------------------------------------------------------------
2426 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2428 wxRegion
* region
= NULL
;
2430 // Combine all the update rects into a region
2431 const wxRectList
& updateRects(win
->GetUpdateRects());
2432 if ( updateRects
.GetCount() != 0 )
2434 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2436 node
= node
->GetNext() )
2438 wxRect
* rect
= node
->GetData();
2441 region
= new wxRegion(*rect
);
2443 // TODO: is this correct? In SetDCClipping above,
2444 // XIntersectRegion is used to combine paint and user
2445 // regions. XIntersectRegion appears to work in that case...
2446 region
->Union(*rect
);
2452 win
->GetClientSize(&cw
, &ch
);
2453 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2456 win
->SetUpdateRegion(*region
);
2458 wxRegion
& theRegion(win
->GetUpdateRegion());
2459 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2461 // Set the clipping region. Any user-defined region will be combined with this
2462 // one in SetDCClipping.
2463 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2468 wxPaintDC::~wxPaintDC()
2470 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2472 m_window
->ClearUpdateRegion();
2475 // ----------------------------------------------------------------------------
2476 // private functions
2477 // ----------------------------------------------------------------------------
2480 Used when copying between drawables on different (Display*) m_displays. Not
2481 very fast, but better than giving up.
2484 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2485 Drawable src
, Drawable dest
,
2488 unsigned int w
, unsigned int h
,
2489 int destx
, int desty
,
2490 bool more
, XImage
**cache
)
2492 XImage
*image
, *destimage
;
2493 Colormap destcm
, srccm
;
2494 static const int CACHE_SIZE
= 256;
2497 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2498 int k
, cache_pos
, all_cache
;
2500 if (!cache
|| !*cache
)
2501 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2505 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2507 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2508 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2513 for (i
= 0; i
< w
; i
++)
2514 for (j
= 0; j
< h
; j
++) {
2515 unsigned long pixel
;
2518 pixel
= XGetPixel(image
, i
, j
);
2519 for (k
= cache_pos
; k
--; )
2520 if (cachesrc
[k
] == pixel
) {
2521 pixel
= cachedest
[k
];
2525 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2526 if (cachesrc
[k
] == pixel
) {
2527 pixel
= cachedest
[k
];
2531 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2532 XQueryColor(src_display
, srccm
, &xcol
);
2533 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2535 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2537 if (++cache_pos
>= CACHE_SIZE
) {
2543 XPutPixel(destimage
, i
, j
, pixel
);
2546 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2547 XDestroyImage(destimage
);
2552 XDestroyImage(image
);
2557 /* Helper function for 16-bit fonts */
2558 static int str16len(const char *s
)
2562 while (s
[0] && s
[1]) {