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 #if !USE_SHARED_LIBRARY
86 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
87 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
88 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
91 // ----------------------------------------------------------------------------
93 // ----------------------------------------------------------------------------
95 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
96 Drawable src
, Drawable dest
,
99 unsigned int w
, unsigned int h
,
100 int destx
, int desty
,
101 bool more
, XImage
**cache
);
103 // ============================================================================
105 // ============================================================================
108 * compare two doubles and return the larger rounded
111 static int roundmax(double a
, double b
)
113 return (int)((a
> b
? a
: b
) + 0.5);
117 * compare two doubles and return the smaller rounded
120 static int roundmin(double a
, double b
)
122 return (int)((a
< b
? a
: b
) - 0.5);
126 // ----------------------------------------------------------------------------
128 // ----------------------------------------------------------------------------
130 wxWindowDC::wxWindowDC()
133 m_gcBacking
= (WXGC
) 0;
135 m_backgroundPixel
= -1;
136 m_currentPenWidth
= 1;
137 m_currentPenJoin
= -1;
138 m_currentPenDashCount
= -1;
139 m_currentPenDash
= (char*) NULL
;
142 // m_currentBkMode = wxTRANSPARENT;
143 m_colour
= wxColourDisplay();
144 m_display
= (WXDisplay
*) NULL
;
145 m_currentRegion
= (WXRegion
) 0;
146 m_userRegion
= (WXRegion
) 0;
147 m_pixmap
= (WXPixmap
) 0;
149 m_oldFont
= (WXFont
) 0;
152 wxWindowDC::wxWindowDC( wxWindow
*window
)
154 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
157 m_font
= window
->GetFont();
159 m_gcBacking
= (WXGC
) 0;
160 m_backgroundPixel
= -1;
161 m_currentPenWidth
= 1;
162 m_currentPenJoin
= -1;
163 m_currentPenDashCount
= -1;
164 m_currentPenDash
= (char*) NULL
;
167 // m_currentBkMode = wxTRANSPARENT;
168 m_colour
= wxColourDisplay();
169 m_currentRegion
= (WXRegion
) 0;
170 m_userRegion
= (WXRegion
) 0;
174 m_display
= window
->GetXDisplay();
175 m_pixmap
= window
->GetXWindow();
176 Display
* display
= (Display
*) m_display
;
178 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
181 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
182 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
183 gcvalues
.graphics_exposures
= False
;
184 gcvalues
.line_width
= 1;
185 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
186 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
189 if (m_window
->GetBackingPixmap())
191 m_gcBacking
= (WXGC
) XCreateGC (display
, RootWindow (display
,
192 DefaultScreen (display
)),
193 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
,
197 m_backgroundPixel
= (int) gcvalues
.background
;
199 // Get the current Font so we can set it back later
201 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
202 m_oldFont
= (WXFont
) valReturn
.font
;
204 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
207 wxWindowDC::~wxWindowDC()
209 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
211 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
213 if (m_window
&& m_window
->GetBackingPixmap())
214 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
218 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
222 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
223 m_gcBacking
= (WXGC
) 0;
226 XDestroyRegion ((Region
) m_currentRegion
);
227 m_currentRegion
= (WXRegion
) 0;
230 XDestroyRegion ((Region
) m_userRegion
);
231 m_userRegion
= (WXRegion
) 0;
234 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
235 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
237 wxFAIL_MSG("not implemented");
240 bool wxWindowDC::DoGetPixel( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
242 wxFAIL_MSG("not implemented");
247 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
249 wxCHECK_RET( Ok(), "invalid dc" );
251 int x1d
, y1d
, x2d
, y2d
;
253 // FreeGetPixelCache();
263 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
265 if (m_window
&& m_window
->GetBackingPixmap())
266 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
267 XLOG2DEV_2(x1
), YLOG2DEV_2(y1
),
268 XLOG2DEV_2(x2
), YLOG2DEV_2(y2
));
270 CalcBoundingBox(x1
, y1
);
271 CalcBoundingBox(x2
, y2
);
274 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
276 wxCHECK_RET( Ok(), "invalid dc" );
281 int xx
= XLOG2DEV (x
);
282 int yy
= YLOG2DEV (y
);
284 wxDisplaySize (&ww
, &hh
);
285 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
287 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
290 if (m_window
&& m_window
->GetBackingPixmap())
294 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
297 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
303 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
305 wxCHECK_RET( Ok(), "invalid dc" );
307 // FreeGetPixelCache();
309 int xx1
= XLOG2DEV (x1
);
310 int yy1
= YLOG2DEV (y1
);
311 int xx2
= XLOG2DEV (x2
);
312 int yy2
= YLOG2DEV (y2
);
313 int xxc
= XLOG2DEV (xc
);
314 int yyc
= YLOG2DEV (yc
);
315 int xxc_2
= XLOG2DEV_2 (xc
);
316 int yyc_2
= YLOG2DEV_2 (yc
);
318 wxCoord dx
= xx1
- xxc
;
319 wxCoord dy
= yy1
- yyc
;
320 double radius
= sqrt (dx
* dx
+ dy
* dy
);
321 wxCoord r
= (wxCoord
) radius
;
323 double radius1
, radius2
;
325 if (xx1
== xx2
&& yy1
== yy2
)
330 else if (radius
== 0.0)
331 radius1
= radius2
= 0.0;
340 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
348 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
352 int alpha1
= (int) radius1
;
353 int alpha2
= (int) (radius2
- radius1
);
356 while (alpha2
> 360 * 64)
359 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
362 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
363 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
365 if (m_window
&& m_window
->GetBackingPixmap())
366 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
367 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
371 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
375 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
376 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
378 if (m_window
&& m_window
->GetBackingPixmap())
379 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
380 xxc_2
- r
, yyc_2
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
382 CalcBoundingBox (x1
, y1
);
383 CalcBoundingBox (x2
, y2
);
386 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
388 wxCHECK_RET( Ok(), "invalid dc" );
394 wd
= XLOG2DEVREL(width
);
395 hd
= YLOG2DEVREL(height
);
397 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
398 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
399 int start
= int(sa
*64);
400 int end
= int(ea
*64);
401 if (start
<0) start
+=360*64;
402 if (end
<0) end
+=360*64;
403 if (end
>start
) end
-=start
;
404 else end
+=360*64-start
;
406 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
408 m_autoSetting
= TRUE
; // must be reset
411 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
413 if (m_window
&& m_window
->GetBackingPixmap())
414 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
415 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
418 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
422 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
423 if (m_window
&& m_window
->GetBackingPixmap())
424 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
425 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),wd
,hd
,start
,end
);
427 CalcBoundingBox (x
, y
);
428 CalcBoundingBox (x
+ width
, y
+ height
);
431 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
433 wxCHECK_RET( Ok(), "invalid dc" );
435 // FreeGetPixelCache();
437 if (m_pen
.Ok() && m_autoSetting
)
440 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
441 if (m_window
&& m_window
->GetBackingPixmap())
442 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, XLOG2DEV_2 (x
), YLOG2DEV_2 (y
));
444 CalcBoundingBox (x
, y
);
447 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
449 wxCHECK_RET( Ok(), "invalid dc" );
451 // FreeGetPixelCache();
453 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
458 XPoint
*xpoints
= new XPoint
[n
];
461 for (i
= 0; i
< n
; i
++)
463 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
464 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
466 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
468 if (m_window
&& m_window
->GetBackingPixmap())
470 for (i
= 0; i
< n
; i
++)
472 xpoints
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
473 xpoints
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
475 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints
, n
, 0);
481 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
482 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
484 wxCHECK_RET( Ok(), "invalid dc" );
486 // FreeGetPixelCache();
488 XPoint
*xpoints1
= new XPoint
[n
+ 1];
489 XPoint
*xpoints2
= new XPoint
[n
+ 1];
491 for (i
= 0; i
< n
; i
++)
493 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
494 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
495 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
496 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
497 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
500 // Close figure for XDrawLines (not needed for XFillPolygon)
501 xpoints1
[i
].x
= xpoints1
[0].x
;
502 xpoints1
[i
].y
= xpoints1
[0].y
;
503 xpoints2
[i
].x
= xpoints2
[0].x
;
504 xpoints2
[i
].y
= xpoints2
[0].y
;
506 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
509 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
510 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
511 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
512 if (m_window
&& m_window
->GetBackingPixmap())
514 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
,
515 fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
516 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
, Complex
, 0);
517 XSetFillRule ((Display
*) m_display
,(GC
) m_gcBacking
, EvenOddRule
); // default mode
521 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
525 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
527 if (m_window
&& m_window
->GetBackingPixmap())
528 XDrawLines ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, xpoints2
, n
+ 1, 0);
535 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
537 wxCHECK_RET( Ok(), "invalid dc" );
539 // FreeGetPixelCache();
541 int xd
, yd
, wfd
, hfd
, wd
, hd
;
545 wfd
= XLOG2DEVREL(width
);
547 hfd
= YLOG2DEVREL(height
);
550 if (wfd
== 0 || hfd
== 0) return;
551 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
552 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
554 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
557 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
559 if (m_window
&& m_window
->GetBackingPixmap())
560 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
561 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
565 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
569 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
571 if (m_window
&& m_window
->GetBackingPixmap())
572 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
573 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
576 CalcBoundingBox (x
, y
);
577 CalcBoundingBox (x
+ width
, y
+ height
);
580 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
582 wxCHECK_RET( Ok(), "invalid dc" );
584 // FreeGetPixelCache();
586 // If radius is negative, it's a proportion of the smaller dimension.
588 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
590 int xd
= XLOG2DEV (x
);
591 int yd
= YLOG2DEV (y
);
592 int rd
= XLOG2DEVREL ((long) radius
);
593 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
594 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
599 // If radius is zero use DrawRectangle() instead to avoid
600 // X drawing errors with small radii
603 DrawRectangle( x
, y
, width
, height
);
607 // Draw nothing if transformed w or h is 0
608 if (wd
== 0 || hd
== 0) return;
610 // CMB: adjust size if outline is drawn otherwise the result is
611 // 1 pixel too wide and high
612 if (m_pen
.GetStyle() != wxTRANSPARENT
)
618 // CMB: ensure dd is not larger than rectangle otherwise we
619 // get an hour glass shape
620 if (rw_d
> wd
) rw_d
= wd
;
621 if (rw_d
> hd
) rw_d
= hd
;
624 // For backing pixmap
625 int xd2
= XLOG2DEV_2 (x
);
626 int yd2
= YLOG2DEV_2 (y
);
627 int rd2
= XLOG2DEVREL ((long) radius
);
628 int wd2
= XLOG2DEVREL (width
) ;
629 int hd2
= YLOG2DEVREL (height
) ;
634 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
638 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
640 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
643 // Arcs start from 3 o'clock, positive angles anticlockwise
645 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
646 rw_d
, rh_d
, 90 * 64, 90 * 64);
648 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
649 // rw_d, rh_d, 0, 90 * 64);
650 rw_d
, rh_d
, 0, 91 * 64);
652 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
654 // rw_d, rh_d, 270 * 64, 90 * 64);
655 rw_d
, rh_d
, 269 * 64, 92 * 64);
657 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
658 rw_d
, rh_d
, 180 * 64, 90 * 64);
660 if (m_window
&& m_window
->GetBackingPixmap())
662 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
663 xd2
+ rd2
, yd2
, wd2
- rw_d2
, hd2
);
664 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
665 xd2
, yd2
+ rd2
, wd2
, hd2
- rh_d2
);
667 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
668 xd2
, yd2
, rw_d2
, rh_d2
, 90 * 64, 90 * 64);
669 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
670 xd2
+ wd2
- rw_d2
, yd2
,
671 // rw_d2, rh_d2, 0, 90 * 64);
672 rw_d2
, rh_d2
, 0, 91 * 64);
673 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
676 // rw_d2, rh_d2, 270 * 64, 90 * 64);
677 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
678 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
679 xd2
, yd2
+ hd2
- rh_d2
,
680 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
684 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
687 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
688 xd
+ wd
- rd
+ 1, yd
);
689 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
690 xd
+ wd
- rd
, yd
+ hd
);
692 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
694 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
695 xd
+ wd
, yd
+ hd
- rd
+ 1);
696 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
697 rw_d
, rh_d
, 90 * 64, 90 * 64);
698 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
699 // rw_d, rh_d, 0, 90 * 64);
700 rw_d
, rh_d
, 0, 91 * 64);
701 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
703 rw_d
, rh_d
, 269 * 64, 92 * 64);
704 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
705 rw_d
, rh_d
, 180 * 64, 90 * 64);
707 if (m_window
&& m_window
->GetBackingPixmap())
709 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
711 xd2
+ wd2
- rd2
+ 1, yd2
);
712 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
713 xd2
+ rd2
, yd2
+ hd2
,
714 xd2
+ wd2
- rd2
, yd2
+ hd2
);
716 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
718 xd2
, yd2
+ hd2
- rd2
);
719 XDrawLine ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
720 xd2
+ wd2
, yd2
+ rd2
,
721 xd2
+ wd2
, yd2
+ hd2
- rd2
+ 1);
722 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
724 rw_d2
, rh_d2
, 90 * 64, 90 * 64);
725 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
726 xd2
+ wd2
- rw_d2
, yd2
,
727 // rw_d2, rh_d2, 0, 90 * 64);
728 rw_d2
, rh_d2
, 0, 91 * 64);
729 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
732 rw_d2
, rh_d2
, 269 * 64, 92 * 64);
733 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
734 xd2
, yd2
+ hd2
- rh_d2
,
735 rw_d2
, rh_d2
, 180 * 64, 90 * 64);
738 CalcBoundingBox (x
, y
);
739 CalcBoundingBox (x
+ width
, y
+ height
);
744 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
746 wxCHECK_RET( Ok(), "invalid dc" );
748 // Check for negative width and height
761 // FreeGetPixelCache();
763 static const int angle
= 23040;
769 wd
= XLOG2DEVREL(width
) ;
770 hd
= YLOG2DEVREL(height
) ;
772 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
775 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
776 if (m_window
&& m_window
->GetBackingPixmap())
777 XFillArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
778 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
779 XLOG2DEVREL (width
) - WX_GC_CF
,
780 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
783 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
787 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
788 if (m_window
&& m_window
->GetBackingPixmap())
789 XDrawArc ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
790 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
),
791 XLOG2DEVREL (width
) - WX_GC_CF
,
792 YLOG2DEVREL (height
) - WX_GC_CF
, 0, angle
);
794 CalcBoundingBox (x
, y
);
795 CalcBoundingBox (x
+ width
, y
+ height
);
799 bool wxWindowDC::CanDrawBitmap() const
801 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
807 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
809 // FreeGetPixelCache();
811 // Be sure that foreground pixels (1) of
812 // the Icon will be painted with pen colour. [m_pen.SetColour()]
813 // Background pixels (0) will be painted with
814 // last selected background color. [::SetBackground]
815 if (m_pen
.Ok() && m_autoSetting
)
819 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
820 width
= icon
.GetWidth();
821 height
= icon
.GetHeight();
822 if (icon
.GetDisplay() == m_display
)
824 if (icon
.GetDepth() <= 1)
826 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
828 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
832 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
834 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
838 if (m_window
&& m_window
->GetBackingPixmap())
840 if (icon
.GetDepth() <= 1)
842 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
843 0, 0, width
, height
, (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), 1);
847 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
849 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
));
852 } else { /* Remote copy (different (Display*) m_displays) */
853 XImage
*cache
= NULL
;
854 if (m_window
&& m_window
->GetBackingPixmap())
855 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
856 (GC
) m_gcBacking
, 0, 0, width
, height
,
857 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
858 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
860 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
862 CalcBoundingBox (x
, y
);
866 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
867 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
868 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
870 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
872 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
874 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
876 // FreeGetPixelCache();
878 // Be sure that foreground pixels (1) of the Icon will be painted with pen
879 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
880 // last selected background color. [::SetBackground]
881 if (m_pen
.Ok() && m_autoSetting
)
884 // Do bitmap scaling if necessary
886 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
887 Pixmap sourcePixmap
= (Pixmap
) NULL
;
888 double scaleX
, scaleY
;
889 GetUserScale(& scaleX
, & scaleY
);
891 // Sorry, can't scale masks just yet
892 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
894 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
895 wxBitmap
& bitmap
= memDC
->GetBitmap();
897 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
899 wxImage
image(bitmap
);
902 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
906 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
907 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
909 image
= image
.Scale(scaledW
, scaledH
);
910 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
911 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
915 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
917 if (m_pixmap
&& sourcePixmap
)
920 int orig
= m_logicalFunction
;
922 SetLogicalFunction (rop
);
924 if (m_display
!= sourceDC
->m_display
)
926 XImage
*cache
= NULL
;
928 if (m_window
&& m_window
->GetBackingPixmap())
929 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
930 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
932 source
->LogicalToDeviceX (xsrc
),
933 source
->LogicalToDeviceY (ysrc
),
934 source
->LogicalToDeviceXRel(width
),
935 source
->LogicalToDeviceYRel(height
),
936 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
939 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
941 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
942 wxBitmap
& sel
= memDC
->GetBitmap();
943 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
945 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
946 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
950 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
951 source
->LogicalToDeviceX (xsrc
),
952 source
->LogicalToDeviceY (ysrc
),
953 source
->LogicalToDeviceXRel(width
),
954 source
->LogicalToDeviceYRel(height
),
955 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
960 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
961 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
966 if (m_window
&& m_window
->GetBackingPixmap())
968 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
969 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) && ((wxMemoryDC
*) source
)->GetBitmap().GetDepth() == 1)
971 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
972 source
->LogicalToDeviceX (xsrc
),
973 source
->LogicalToDeviceY (ysrc
),
974 source
->LogicalToDeviceXRel(width
),
975 source
->LogicalToDeviceYRel(height
),
976 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
), 1);
980 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
981 source
->LogicalToDeviceX (xsrc
),
982 source
->LogicalToDeviceY (ysrc
),
983 source
->LogicalToDeviceXRel(width
),
984 source
->LogicalToDeviceYRel(height
),
985 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
));
988 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
990 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
991 wxBitmap
& sel
= memDC
->GetBitmap();
992 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
994 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
995 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
999 // Check if we're copying from a mono bitmap
1000 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
1001 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
1003 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1004 source
->LogicalToDeviceX (xsrc
),
1005 source
->LogicalToDeviceY (ysrc
),
1006 source
->LogicalToDeviceXRel(width
),
1007 source
->LogicalToDeviceYRel(height
),
1008 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
1012 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
1013 source
->LogicalToDeviceX (xsrc
),
1014 source
->LogicalToDeviceY (ysrc
),
1015 source
->LogicalToDeviceXRel(width
),
1016 source
->LogicalToDeviceYRel(height
),
1017 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
1022 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1023 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
1026 } /* Remote/local (Display*) m_display */
1027 CalcBoundingBox (xdest
, ydest
);
1028 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
1030 SetLogicalFunction(orig
);
1032 if (scaledBitmap
) delete scaledBitmap
;
1036 if (scaledBitmap
) delete scaledBitmap
;
1041 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1043 wxCHECK_RET( Ok(), "invalid dc" );
1045 // Since X draws from the baseline of the text, must add the text height
1051 slen
= strlen(text
);
1055 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1056 int direction
, descent
;
1057 XCharStruct overall_return
;
1060 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1061 &ascent
, &descent
, &overall_return
);
1064 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1065 &ascent
, &descent
, &overall_return
);
1067 cx
= overall_return
.width
;
1068 cy
= ascent
+ descent
;
1071 // First draw a rectangle representing the text background, if a text
1072 // background is specified
1073 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1075 wxColour oldPenColour
= m_currentColour
;
1076 m_currentColour
= m_textBackgroundColour
;
1077 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1078 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1079 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1080 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1082 // This separation of the big && test required for gcc2.7/HP UX 9.02
1083 // or pixel value can be corrupted!
1084 sameColour
= (sameColour
&&
1085 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1087 if (!sameColour
|| !GetOptimization())
1089 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1090 m_currentColour
= m_textBackgroundColour
;
1092 // Set the GC to the required colour
1095 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1096 if (m_window
&& m_window
->GetBackingPixmap())
1097 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1101 m_textBackgroundColour
= oldPenColour
;
1103 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1104 if (m_window
&& m_window
->GetBackingPixmap())
1105 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1106 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1109 // Now set the text foreground and draw the text
1110 if (m_textForegroundColour
.Ok ())
1112 wxColour oldPenColour
= m_currentColour
;
1113 m_currentColour
= m_textForegroundColour
;
1114 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
1115 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1116 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1117 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1118 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1120 if (!sameColour
|| !GetOptimization())
1123 if (!m_colour
) // Mono display
1125 // Unless foreground is really white, draw it in black
1126 unsigned char red
= m_textForegroundColour
.Red ();
1127 unsigned char blue
= m_textForegroundColour
.Blue ();
1128 unsigned char green
= m_textForegroundColour
.Green ();
1129 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1130 && green
== (unsigned char) 255)
1132 m_currentColour
= *wxWHITE
;
1133 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1134 m_currentColour
.SetPixel(pixel
);
1135 m_textForegroundColour
.SetPixel(pixel
);
1139 m_currentColour
= *wxBLACK
;
1140 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1141 m_currentColour
.SetPixel(pixel
);
1142 m_textForegroundColour
.SetPixel(pixel
);
1147 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
1148 m_currentColour
.SetPixel(pixel
);
1151 // Set the GC to the required colour
1154 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1155 if (m_window
&& m_window
->GetBackingPixmap())
1156 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1160 m_textForegroundColour
= oldPenColour
;
1163 // We need to add the ascent, not the whole height, since X draws at the
1164 // point above the descender.
1167 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1168 (XChar2b
*)(char*) (const char*) text
, slen
);
1171 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1173 if (m_window
&& m_window
->GetBackingPixmap()) {
1176 XDrawString16((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1177 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
,
1178 (XChar2b
*)(char*) (const char*) text
, slen
);
1181 XDrawString((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(), (GC
) m_gcBacking
,
1182 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
) + ascent
, (char*) (const char*) text
, slen
);
1186 GetTextExtent (text
, &w
, &h
);
1187 CalcBoundingBox (x
+ w
, y
+ h
);
1188 CalcBoundingBox (x
, y
);
1191 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1195 DrawText(text
, x
, y
);
1199 wxCHECK_RET( Ok(), "invalid dc" );
1201 // Since X draws from the baseline of the text, must add the text height
1207 slen
= strlen(text
);
1211 // Calculate text extent.
1212 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1213 int direction
, descent
;
1214 XCharStruct overall_return
;
1217 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1218 &ascent
, &descent
, &overall_return
);
1221 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1222 &ascent
, &descent
, &overall_return
);
1224 cx
= overall_return
.width
;
1225 cy
= ascent
+ descent
;
1228 wxBitmap
src(cx
, cy
);
1230 dc
.SelectObject(src
);
1231 dc
.SetFont(GetFont());
1232 dc
.SetBackground(*wxWHITE_BRUSH
);
1233 dc
.SetBrush(*wxBLACK_BRUSH
);
1235 dc
.DrawText(text
, 0, 0);
1236 dc
.SetFont(wxNullFont
);
1238 // Calculate the size of the rotated bounding box.
1239 double dx
= cos(angle
/ 180.0 * M_PI
);
1240 double dy
= sin(angle
/ 180.0 * M_PI
);
1241 double x4
= -cy
* dy
;
1242 double y4
= cy
* dx
;
1243 double x3
= cx
* dx
;
1244 double y3
= cx
* dy
;
1245 double x2
= x3
+ x4
;
1246 double y2
= y3
+ y4
;
1250 // Create image from the source bitmap after writing the text into it.
1253 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1254 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1255 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1256 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1258 // This rotates counterclockwise around the top left corner.
1259 for (int rx
= minx
; rx
< maxx
; rx
++)
1261 for (int ry
= miny
; ry
< maxy
; ry
++)
1263 // transform dest coords to source coords
1264 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1265 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1266 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1268 // draw black pixels, ignore white ones (i.e. transparent b/g)
1269 if (image
.GetRed(sx
, sy
) == 0)
1271 DrawPoint(x1
+ maxx
- rx
, cy
+ y1
- ry
);
1276 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1283 // First draw a rectangle representing the text background, if a text
1284 // background is specified
1285 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1287 wxColour oldPenColour
= m_currentColour
;
1288 m_currentColour
= m_textBackgroundColour
;
1289 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1290 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1291 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1292 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1294 // This separation of the big && test required for gcc2.7/HP UX 9.02
1295 // or pixel value can be corrupted!
1296 sameColour
= (sameColour
&&
1297 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1299 if (!sameColour
|| !GetOptimization())
1301 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1302 m_currentColour
= m_textBackgroundColour
;
1304 // Set the GC to the required colour
1307 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1308 if (m_window
&& m_window
->GetBackingPixmap())
1309 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1313 m_textBackgroundColour
= oldPenColour
;
1315 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1316 if (m_window
&& m_window
->GetBackingPixmap())
1317 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1318 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1323 // XXX use pixmap size
1324 GetTextExtent (text
, &w
, &h
);
1325 CalcBoundingBox (x
+ w
, y
+ h
);
1326 CalcBoundingBox (x
, y
);
1329 bool wxWindowDC::CanGetTextExtent() const
1334 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1335 wxCoord
*descent
, wxCoord
*externalLeading
,
1336 wxFont
*font
) const
1338 wxCHECK_RET( Ok(), "invalid dc" );
1340 wxFont
* theFont
= font
;
1342 theFont
= (wxFont
*)&m_font
; // const_cast
1346 // TODO: this should be an error log function
1347 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1349 if (width
) *width
= -1;
1350 if (height
) *height
= -1;
1354 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1356 int direction
, ascent
, descent2
;
1357 XCharStruct overall
;
1362 slen
= str16len(string
);
1365 slen
= strlen(string
);
1369 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1370 &ascent
, &descent2
, &overall
);
1373 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1374 &ascent
, &descent2
, &overall
);
1376 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1377 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1379 *descent
= descent2
;
1380 if (externalLeading
)
1381 *externalLeading
= 0;
1384 wxCoord
wxWindowDC::GetCharWidth() const
1386 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1387 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1389 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1391 int direction
, ascent
, descent
;
1392 XCharStruct overall
;
1393 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1394 &descent
, &overall
);
1395 return XDEV2LOGREL(overall
.width
);
1398 wxCoord
wxWindowDC::GetCharHeight() const
1400 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1401 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1403 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1405 int direction
, ascent
, descent
;
1406 XCharStruct overall
;
1407 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1408 &descent
, &overall
);
1409 // return XDEV2LOGREL(overall.ascent + overall.descent);
1410 return XDEV2LOGREL(ascent
+ descent
);
1413 void wxWindowDC::Clear()
1415 wxCHECK_RET( Ok(), "invalid dc" );
1420 m_window
->GetSize(&w
, &h
);
1422 if (m_window
&& m_window
->GetBackingPixmap())
1424 w
= m_window
->GetPixmapWidth();
1425 h
= m_window
->GetPixmapHeight();
1430 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1432 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1433 w
= memDC
->GetBitmap().GetWidth();
1434 h
= memDC
->GetBitmap().GetHeight();
1440 wxBrush saveBrush
= m_brush
;
1441 SetBrush (m_backgroundBrush
);
1443 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1445 if (m_window
&& m_window
->GetBackingPixmap())
1446 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1448 m_brush
= saveBrush
;
1451 void wxWindowDC::Clear(const wxRect
& rect
)
1453 wxCHECK_RET( Ok(), "invalid dc" );
1455 int x
= rect
.x
; int y
= rect
.y
;
1456 int w
= rect
.width
; int h
= rect
.height
;
1458 wxBrush saveBrush
= m_brush
;
1459 SetBrush (m_backgroundBrush
);
1461 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1463 if (m_window
&& m_window
->GetBackingPixmap())
1464 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1466 m_brush
= saveBrush
;
1469 void wxWindowDC::SetFont( const wxFont
&font
)
1471 wxCHECK_RET( Ok(), "invalid dc" );
1477 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1479 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1481 if (m_window
&& m_window
->GetBackingPixmap())
1482 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1487 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1489 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1490 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1492 if (m_window
&& m_window
->GetBackingPixmap())
1493 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1496 void wxWindowDC::SetPen( const wxPen
&pen
)
1498 wxCHECK_RET( Ok(), "invalid dc" );
1504 wxBitmap oldStipple
= m_currentStipple
;
1505 int oldStyle
= m_currentStyle
;
1506 int oldFill
= m_currentFill
;
1507 int old_pen_width
= m_currentPenWidth
;
1508 int old_pen_join
= m_currentPenJoin
;
1509 int old_pen_cap
= m_currentPenCap
;
1510 int old_pen_nb_dash
= m_currentPenDashCount
;
1511 char *old_pen_dash
= m_currentPenDash
;
1513 wxColour oldPenColour
= m_currentColour
;
1514 m_currentColour
= m_pen
.GetColour ();
1515 m_currentStyle
= m_pen
.GetStyle ();
1516 m_currentFill
= m_pen
.GetStyle (); // TODO?
1517 m_currentPenWidth
= m_pen
.GetWidth ();
1518 m_currentPenJoin
= m_pen
.GetJoin ();
1519 m_currentPenCap
= m_pen
.GetCap ();
1520 m_currentPenDashCount
= m_pen
.GetDashCount();
1521 m_currentPenDash
= m_pen
.GetDash();
1523 if (m_currentStyle
== wxSTIPPLE
)
1524 m_currentStipple
= * m_pen
.GetStipple ();
1526 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1527 oldFill
== m_currentFill
&&
1528 old_pen_join
== m_currentPenJoin
&&
1529 old_pen_cap
== m_currentPenCap
&&
1530 old_pen_nb_dash
== m_currentPenDashCount
&&
1531 old_pen_dash
== m_currentPenDash
&&
1532 old_pen_width
== m_currentPenWidth
);
1534 bool sameColour
= (oldPenColour
.Ok () &&
1535 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1536 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1537 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1538 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1540 if (!sameStyle
|| !GetOptimization())
1542 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1543 if (scaled_width
< 0)
1549 static const char dotted
[] = {2, 5};
1550 static const char short_dashed
[] = {4, 4};
1551 static const char long_dashed
[] = {4, 8};
1552 static const char dotted_dashed
[] = {6, 6, 2, 6};
1554 // We express dash pattern in pen width unit, so we are
1555 // independent of zoom factor and so on...
1557 const char *req_dash
;
1559 switch (m_pen
.GetStyle ())
1562 req_nb_dash
= m_currentPenDashCount
;
1563 req_dash
= m_currentPenDash
;
1564 style
= LineOnOffDash
;
1569 style
= LineOnOffDash
;
1573 req_dash
= short_dashed
;
1574 style
= LineOnOffDash
;
1578 req_dash
= long_dashed
;
1579 style
= LineOnOffDash
;
1583 req_dash
= dotted_dashed
;
1584 style
= LineOnOffDash
;
1595 if (req_dash
&& req_nb_dash
)
1597 char *real_req_dash
= new char[req_nb_dash
];
1600 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1601 for (int i
= 0; i
< req_nb_dash
; i
++)
1602 real_req_dash
[i
] = req_dash
[i
] * factor
;
1603 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1605 if (m_window
&& m_window
->GetBackingPixmap())
1606 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1607 delete[]real_req_dash
;
1611 // No Memory. We use non-scaled dash pattern...
1612 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1614 if (m_window
&& m_window
->GetBackingPixmap())
1615 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1619 switch (m_pen
.GetCap ())
1621 case wxCAP_PROJECTING
:
1622 cap
= CapProjecting
;
1629 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1633 switch (m_pen
.GetJoin ())
1647 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1649 if (m_window
&& m_window
->GetBackingPixmap())
1650 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1653 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1657 oldStipple
= wxNullBitmap
; // For later reset!!
1659 switch (m_currentFill
)
1661 case wxBDIAGONAL_HATCH
:
1662 if (bdiag
== (Pixmap
) 0)
1663 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1664 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1665 bdiag_bits
, bdiag_width
, bdiag_height
);
1668 case wxFDIAGONAL_HATCH
:
1669 if (fdiag
== (Pixmap
) 0)
1670 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1671 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1672 fdiag_bits
, fdiag_width
, fdiag_height
);
1676 if (cross
== (Pixmap
) 0)
1677 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1678 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1679 cross_bits
, cross_width
, cross_height
);
1682 case wxHORIZONTAL_HATCH
:
1683 if (horiz
== (Pixmap
) 0)
1684 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1685 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1686 horiz_bits
, horiz_width
, horiz_height
);
1689 case wxVERTICAL_HATCH
:
1690 if (verti
== (Pixmap
) 0)
1691 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1692 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1693 verti_bits
, verti_width
, verti_height
);
1696 case wxCROSSDIAG_HATCH
:
1698 if (cdiag
== (Pixmap
) 0)
1699 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1700 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1701 cdiag_bits
, cdiag_width
, cdiag_height
);
1705 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1707 if (m_window
&& m_window
->GetBackingPixmap())
1708 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1710 else if (m_currentStipple
.Ok()
1711 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1713 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1715 if (m_window
&& m_window
->GetBackingPixmap())
1716 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1719 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1723 if (m_currentFill
== wxSTIPPLE
)
1724 fill_style
= FillStippled
;
1725 else if (IS_HATCH (m_currentFill
))
1726 fill_style
= FillStippled
;
1728 fill_style
= FillSolid
;
1729 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1730 if (m_window
&& m_window
->GetBackingPixmap())
1731 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1734 // must test m_logicalFunction, because it involves background!
1735 if (!sameColour
|| !GetOptimization()
1736 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1739 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1740 pixel
= m_backgroundPixel
;
1743 unsigned char red
= m_pen
.GetColour ().Red ();
1744 unsigned char blue
= m_pen
.GetColour ().Blue ();
1745 unsigned char green
= m_pen
.GetColour ().Green ();
1746 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1747 && green
== (unsigned char) 255)
1749 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1750 m_currentColour
= *wxWHITE
;
1751 m_pen
.GetColour().SetPixel(pixel
);
1752 m_currentColour
.SetPixel(pixel
);
1756 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1757 m_currentColour
= *wxBLACK
;
1758 m_pen
.GetColour().SetPixel(pixel
);
1763 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1764 m_currentColour
.SetPixel(pixel
);
1767 // Finally, set the GC to the required colour
1770 if (m_logicalFunction
== wxXOR
)
1773 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1774 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1775 if (m_window
&& m_window
->GetBackingPixmap())
1776 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1780 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1781 if (m_window
&& m_window
->GetBackingPixmap())
1782 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1787 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1792 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1794 wxCHECK_RET( Ok(), "invalid dc" );
1798 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1801 int oldFill
= m_currentFill
;
1802 wxBitmap oldStipple
= m_currentStipple
;
1804 m_autoSetting
|= 0x1;
1806 m_currentFill
= m_brush
.GetStyle ();
1807 if (m_currentFill
== wxSTIPPLE
)
1808 m_currentStipple
= * m_brush
.GetStipple ();
1810 wxColour
oldBrushColour(m_currentColour
);
1811 m_currentColour
= m_brush
.GetColour ();
1813 bool sameColour
= (oldBrushColour
.Ok () &&
1814 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1815 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1816 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1817 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1819 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1821 switch (brush
.GetStyle ())
1825 case wxBDIAGONAL_HATCH
:
1826 case wxCROSSDIAG_HATCH
:
1827 case wxFDIAGONAL_HATCH
:
1829 case wxHORIZONTAL_HATCH
:
1830 case wxVERTICAL_HATCH
:
1833 // Chris Breeze 23/07/97: use background mode to determine whether
1834 // fill style should be solid or transparent
1835 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1836 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1837 if (m_window
&& m_window
->GetBackingPixmap())
1838 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1843 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1844 if (m_window
&& m_window
->GetBackingPixmap())
1845 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1849 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1853 switch (m_currentFill
)
1855 case wxBDIAGONAL_HATCH
:
1856 if (bdiag
== (Pixmap
) 0)
1857 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1858 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1859 bdiag_bits
, bdiag_width
, bdiag_height
);
1862 case wxFDIAGONAL_HATCH
:
1863 if (fdiag
== (Pixmap
) 0)
1864 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1865 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1866 fdiag_bits
, fdiag_width
, fdiag_height
);
1870 if (cross
== (Pixmap
) 0)
1871 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1872 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1873 cross_bits
, cross_width
, cross_height
);
1876 case wxHORIZONTAL_HATCH
:
1877 if (horiz
== (Pixmap
) 0)
1878 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1879 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1880 horiz_bits
, horiz_width
, horiz_height
);
1883 case wxVERTICAL_HATCH
:
1884 if (verti
== (Pixmap
) 0)
1885 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1886 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1887 verti_bits
, verti_width
, verti_height
);
1890 case wxCROSSDIAG_HATCH
:
1892 if (cdiag
== (Pixmap
) 0)
1893 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1894 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1895 cdiag_bits
, cdiag_width
, cdiag_height
);
1899 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1901 if (m_window
&& m_window
->GetBackingPixmap())
1902 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1904 // X can forget the stipple value when resizing a window (apparently)
1905 // so always set the stipple.
1906 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1908 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1909 if (m_window
&& m_window
->GetBackingPixmap())
1910 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1913 // must test m_logicalFunction, because it involves background!
1914 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1919 // Policy - on a monochrome screen, all brushes are white,
1920 // except when they're REALLY black!!!
1921 unsigned char red
= m_brush
.GetColour ().Red ();
1922 unsigned char blue
= m_brush
.GetColour ().Blue ();
1923 unsigned char green
= m_brush
.GetColour ().Green ();
1925 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1926 && green
== (unsigned char) 0)
1928 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1929 m_currentColour
= *wxBLACK
;
1930 m_brush
.GetColour().SetPixel(pixel
);
1931 m_currentColour
.SetPixel(pixel
);
1935 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1936 m_currentColour
= *wxWHITE
;
1937 m_brush
.GetColour().SetPixel(pixel
);
1938 m_currentColour
.SetPixel(pixel
);
1941 // N.B. comment out the above line and uncomment the following lines
1942 // if you want non-white colours to be black on a monochrome display.
1944 if (red == (unsigned char )255 && blue == (unsigned char)255
1945 && green == (unsigned char)255)
1946 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1948 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1951 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1953 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1954 m_currentColour
.SetPixel(pixel
);
1958 // Finally, set the GC to the required colour
1959 if (m_logicalFunction
== wxXOR
)
1962 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1963 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1964 if (m_window
&& m_window
->GetBackingPixmap())
1965 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1969 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1970 if (m_window
&& m_window
->GetBackingPixmap())
1971 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1976 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1979 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1981 wxCHECK_RET( Ok(), "invalid dc" );
1983 m_backgroundBrush
= brush
;
1985 if (!m_backgroundBrush
.Ok())
1988 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1990 // New behaviour, 10/2/99: setting the background brush of a DC
1991 // doesn't affect the window background colour.
1993 // XSetWindowBackground doesn't work for non-Window pixmaps
1994 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1995 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1998 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1999 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2000 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2001 if (m_window
&& m_window
->GetBackingPixmap())
2002 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2005 void wxWindowDC::SetLogicalFunction( int function
)
2007 wxCHECK_RET( Ok(), "invalid dc" );
2012 if (m_logicalFunction
== function
)
2018 x_function
= GXclear
;
2024 x_function
= GXinvert
;
2027 x_function
= GXorReverse
;
2030 x_function
= GXandReverse
;
2039 x_function
= GXandInverted
;
2042 x_function
= GXnoop
;
2048 x_function
= GXequiv
;
2051 x_function
= GXcopyInverted
;
2054 x_function
= GXorInverted
;
2057 x_function
= GXnand
;
2064 x_function
= GXcopy
;
2068 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2069 if (m_window
&& m_window
->GetBackingPixmap())
2070 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2072 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2073 /* MATTHEW: [9] Need to redo pen simply */
2074 m_autoSetting
|= 0x2;
2076 m_logicalFunction
= function
;
2080 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2082 wxCHECK_RET( Ok(), "invalid dc" );
2084 if (m_textForegroundColour
== col
)
2087 m_textForegroundColour
= col
;
2091 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2093 wxCHECK_RET( Ok(), "invalid dc" );
2095 if (m_textBackgroundColour
== col
)
2098 m_textBackgroundColour
= col
;
2099 if (!m_textBackgroundColour
.Ok())
2103 void wxWindowDC::SetBackgroundMode( int mode
)
2105 m_backgroundMode
= mode
;
2108 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2113 /* Use GetXColormap */
2114 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2115 (Colormap
) palette
.GetXColormap());
2117 /* Use wxGetMainColormap */
2118 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2119 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2124 void wxWindowDC::SetDCClipping()
2126 // m_userRegion is the region set by calling SetClippingRegion
2128 if (m_currentRegion
)
2129 XDestroyRegion ((Region
) m_currentRegion
);
2131 // We need to take into account
2132 // clipping imposed on a window by a repaint.
2133 // We'll combine it with the user region. But for now,
2134 // just use the currently-defined user clipping region.
2135 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2136 m_currentRegion
= (WXRegion
) XCreateRegion ();
2138 m_currentRegion
= (WXRegion
) NULL
;
2140 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2141 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2142 else if (m_userRegion
)
2143 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2144 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2145 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2146 (Region
) m_currentRegion
);
2148 if (m_currentRegion
)
2150 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2154 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2159 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2161 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2164 XDestroyRegion ((Region
) m_userRegion
);
2165 m_userRegion
= (WXRegion
) XCreateRegion ();
2169 r
.width
= XLOG2DEVREL(width
);
2170 r
.height
= YLOG2DEVREL(height
);
2171 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2175 // Needs to work differently for Pixmap: without this,
2176 // there's a nasty (Display*) m_display bug. 8/12/94
2177 if (m_window
&& m_window
->GetBackingPixmap())
2179 XRectangle rects
[1];
2180 rects
[0].x
= XLOG2DEV_2(x
);
2181 rects
[0].y
= YLOG2DEV_2(y
);
2182 rects
[0].width
= XLOG2DEVREL(width
);
2183 rects
[0].height
= YLOG2DEVREL(height
);
2184 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2188 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2190 wxRect box
= region
.GetBox();
2192 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2195 XDestroyRegion ((Region
) m_userRegion
);
2196 m_userRegion
= (WXRegion
) XCreateRegion ();
2198 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2202 // Needs to work differently for Pixmap: without this,
2203 // there's a nasty (Display*) m_display bug. 8/12/94
2204 if (m_window
&& m_window
->GetBackingPixmap())
2206 XRectangle rects
[1];
2207 rects
[0].x
= XLOG2DEV_2(box
.x
);
2208 rects
[0].y
= YLOG2DEV_2(box
.y
);
2209 rects
[0].width
= XLOG2DEVREL(box
.width
);
2210 rects
[0].height
= YLOG2DEVREL(box
.height
);
2211 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2216 void wxWindowDC::DestroyClippingRegion()
2218 wxDC::DestroyClippingRegion();
2221 XDestroyRegion ((Region
) m_userRegion
);
2222 m_userRegion
= NULL
;
2227 gc_val
.clip_mask
= None
;
2228 if (m_window
&& m_window
->GetBackingPixmap())
2229 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2232 // Resolution in pixels per logical inch
2233 wxSize
wxWindowDC::GetPPI() const
2235 return wxSize(100, 100);
2238 int wxWindowDC::GetDepth() const
2245 // ----------------------------------- spline code ----------------------------------------
2247 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2248 double a3
, double b3
, double a4
, double b4
);
2249 void wx_clear_stack();
2250 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2251 double *y3
, double *x4
, double *y4
);
2252 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2253 double x4
, double y4
);
2254 static bool wx_spline_add_point(double x
, double y
);
2255 static void wx_spline_draw_point_array(wxDC
*dc
);
2257 wxList wx_spline_point_list
;
2259 #define half(z1, z2) ((z1+z2)/2.0)
2262 /* iterative version */
2264 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2267 register double xmid
, ymid
;
2268 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2271 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2273 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2274 xmid
= (double)half(x2
, x3
);
2275 ymid
= (double)half(y2
, y3
);
2276 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2277 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2278 wx_spline_add_point( x1
, y1
);
2279 wx_spline_add_point( xmid
, ymid
);
2281 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2282 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2283 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2284 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2289 /* utilities used by spline drawing routines */
2291 typedef struct wx_spline_stack_struct
{
2292 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2295 #define SPLINE_STACK_DEPTH 20
2296 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2297 static Stack
*wx_stack_top
;
2298 static int wx_stack_count
;
2300 void wx_clear_stack()
2302 wx_stack_top
= wx_spline_stack
;
2306 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2308 wx_stack_top
->x1
= x1
;
2309 wx_stack_top
->y1
= y1
;
2310 wx_stack_top
->x2
= x2
;
2311 wx_stack_top
->y2
= y2
;
2312 wx_stack_top
->x3
= x3
;
2313 wx_stack_top
->y3
= y3
;
2314 wx_stack_top
->x4
= x4
;
2315 wx_stack_top
->y4
= y4
;
2320 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2321 double *x3
, double *y3
, double *x4
, double *y4
)
2323 if (wx_stack_count
== 0)
2327 *x1
= wx_stack_top
->x1
;
2328 *y1
= wx_stack_top
->y1
;
2329 *x2
= wx_stack_top
->x2
;
2330 *y2
= wx_stack_top
->y2
;
2331 *x3
= wx_stack_top
->x3
;
2332 *y3
= wx_stack_top
->y3
;
2333 *x4
= wx_stack_top
->x4
;
2334 *y4
= wx_stack_top
->y4
;
2338 static bool wx_spline_add_point(double x
, double y
)
2340 wxPoint
*point
= new wxPoint
;
2343 wx_spline_point_list
.Append((wxObject
*)point
);
2347 static void wx_spline_draw_point_array(wxDC
*dc
)
2349 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2350 wxNode
*node
= wx_spline_point_list
.First();
2353 wxPoint
*point
= (wxPoint
*)node
->Data();
2356 node
= wx_spline_point_list
.First();
2360 void wxWindowDC::DoDrawSpline( wxList
*points
)
2362 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2365 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2366 double x1
, y1
, x2
, y2
;
2368 wxNode
*node
= points
->First();
2369 p
= (wxPoint
*)node
->Data();
2374 node
= node
->Next();
2375 p
= (wxPoint
*)node
->Data();
2379 cx1
= (double)((x1
+ x2
) / 2);
2380 cy1
= (double)((y1
+ y2
) / 2);
2381 cx2
= (double)((cx1
+ x2
) / 2);
2382 cy2
= (double)((cy1
+ y2
) / 2);
2384 wx_spline_add_point(x1
, y1
);
2386 while ((node
= node
->Next()) != NULL
)
2388 p
= (wxPoint
*)node
->Data();
2393 cx4
= (double)(x1
+ x2
) / 2;
2394 cy4
= (double)(y1
+ y2
) / 2;
2395 cx3
= (double)(x1
+ cx4
) / 2;
2396 cy3
= (double)(y1
+ cy4
) / 2;
2398 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2402 cx2
= (double)(cx1
+ x2
) / 2;
2403 cy2
= (double)(cy1
+ y2
) / 2;
2406 wx_spline_add_point( cx1
, cy1
);
2407 wx_spline_add_point( x2
, y2
);
2409 wx_spline_draw_point_array( this );
2412 #endif // wxUSE_SPLINE
2416 // ----------------------------------------------------------------------------
2418 // ----------------------------------------------------------------------------
2420 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2422 wxRegion
* region
= NULL
;
2424 // Combine all the update rects into a region
2425 const wxRectList
& updateRects(win
->GetUpdateRects());
2426 if ( updateRects
.GetCount() != 0 )
2428 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2430 node
= node
->GetNext() )
2432 wxRect
* rect
= node
->GetData();
2435 region
= new wxRegion(*rect
);
2437 // TODO: is this correct? In SetDCClipping above,
2438 // XIntersectRegion is used to combine paint and user
2439 // regions. XIntersectRegion appears to work in that case...
2440 region
->Union(*rect
);
2446 win
->GetClientSize(&cw
, &ch
);
2447 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2450 win
->SetUpdateRegion(*region
);
2452 wxRegion
& theRegion(win
->GetUpdateRegion());
2453 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2455 // Set the clipping region. Any user-defined region will be combined with this
2456 // one in SetDCClipping.
2457 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2462 wxPaintDC::~wxPaintDC()
2464 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2466 m_window
->ClearUpdateRegion();
2469 // ----------------------------------------------------------------------------
2470 // private functions
2471 // ----------------------------------------------------------------------------
2474 Used when copying between drawables on different (Display*) m_displays. Not
2475 very fast, but better than giving up.
2478 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2479 Drawable src
, Drawable dest
,
2482 unsigned int w
, unsigned int h
,
2483 int destx
, int desty
,
2484 bool more
, XImage
**cache
)
2486 XImage
*image
, *destimage
;
2487 Colormap destcm
, srccm
;
2488 static const int CACHE_SIZE
= 256;
2491 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2492 int k
, cache_pos
, all_cache
;
2494 if (!cache
|| !*cache
)
2495 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2499 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2501 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2502 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2507 for (i
= 0; i
< w
; i
++)
2508 for (j
= 0; j
< h
; j
++) {
2509 unsigned long pixel
;
2512 pixel
= XGetPixel(image
, i
, j
);
2513 for (k
= cache_pos
; k
--; )
2514 if (cachesrc
[k
] == pixel
) {
2515 pixel
= cachedest
[k
];
2519 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2520 if (cachesrc
[k
] == pixel
) {
2521 pixel
= cachedest
[k
];
2525 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2526 XQueryColor(src_display
, srccm
, &xcol
);
2527 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2529 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2531 if (++cache_pos
>= CACHE_SIZE
) {
2537 XPutPixel(destimage
, i
, j
, pixel
);
2540 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2541 XDestroyImage(destimage
);
2546 XDestroyImage(image
);
2551 /* Helper function for 16-bit fonts */
2552 static int str16len(const char *s
)
2556 while (s
[0] && s
[1]) {