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)
1272 DrawPoint(x1
+ maxx
- rx
, cy
+ y1
- ry
);
1277 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1284 // First draw a rectangle representing the text background, if a text
1285 // background is specified
1286 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1288 wxColour oldPenColour
= m_currentColour
;
1289 m_currentColour
= m_textBackgroundColour
;
1290 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1291 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1292 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1293 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1295 // This separation of the big && test required for gcc2.7/HP UX 9.02
1296 // or pixel value can be corrupted!
1297 sameColour
= (sameColour
&&
1298 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1300 if (!sameColour
|| !GetOptimization())
1302 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1303 m_currentColour
= m_textBackgroundColour
;
1305 // Set the GC to the required colour
1308 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1309 if (m_window
&& m_window
->GetBackingPixmap())
1310 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1314 m_textBackgroundColour
= oldPenColour
;
1316 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1317 if (m_window
&& m_window
->GetBackingPixmap())
1318 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
,
1319 XLOG2DEV_2 (x
), YLOG2DEV_2 (y
), cx
, cy
);
1324 // XXX use pixmap size
1325 GetTextExtent (text
, &w
, &h
);
1326 CalcBoundingBox (x
+ w
, y
+ h
);
1327 CalcBoundingBox (x
, y
);
1330 bool wxWindowDC::CanGetTextExtent() const
1335 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1336 wxCoord
*descent
, wxCoord
*externalLeading
,
1337 wxFont
*font
) const
1339 wxCHECK_RET( Ok(), "invalid dc" );
1341 wxFont
* theFont
= font
;
1343 theFont
= (wxFont
*)&m_font
; // const_cast
1347 // TODO: this should be an error log function
1348 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1350 if (width
) *width
= -1;
1351 if (height
) *height
= -1;
1355 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1357 int direction
, ascent
, descent2
;
1358 XCharStruct overall
;
1363 slen
= str16len(string
);
1366 slen
= strlen(string
);
1370 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1371 &ascent
, &descent2
, &overall
);
1374 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1375 &ascent
, &descent2
, &overall
);
1377 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1378 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1380 *descent
= descent2
;
1381 if (externalLeading
)
1382 *externalLeading
= 0;
1385 wxCoord
wxWindowDC::GetCharWidth() const
1387 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1388 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1390 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1392 int direction
, ascent
, descent
;
1393 XCharStruct overall
;
1394 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1395 &descent
, &overall
);
1396 return XDEV2LOGREL(overall
.width
);
1399 wxCoord
wxWindowDC::GetCharHeight() const
1401 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1402 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1404 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1406 int direction
, ascent
, descent
;
1407 XCharStruct overall
;
1408 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1409 &descent
, &overall
);
1410 // return XDEV2LOGREL(overall.ascent + overall.descent);
1411 return XDEV2LOGREL(ascent
+ descent
);
1414 void wxWindowDC::Clear()
1416 wxCHECK_RET( Ok(), "invalid dc" );
1421 m_window
->GetSize(&w
, &h
);
1423 if (m_window
&& m_window
->GetBackingPixmap())
1425 w
= m_window
->GetPixmapWidth();
1426 h
= m_window
->GetPixmapHeight();
1431 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1433 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1434 w
= memDC
->GetBitmap().GetWidth();
1435 h
= memDC
->GetBitmap().GetHeight();
1441 wxBrush saveBrush
= m_brush
;
1442 SetBrush (m_backgroundBrush
);
1444 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1446 if (m_window
&& m_window
->GetBackingPixmap())
1447 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, 0, 0, w
, h
);
1449 m_brush
= saveBrush
;
1452 void wxWindowDC::Clear(const wxRect
& rect
)
1454 wxCHECK_RET( Ok(), "invalid dc" );
1456 int x
= rect
.x
; int y
= rect
.y
;
1457 int w
= rect
.width
; int h
= rect
.height
;
1459 wxBrush saveBrush
= m_brush
;
1460 SetBrush (m_backgroundBrush
);
1462 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1464 if (m_window
&& m_window
->GetBackingPixmap())
1465 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_window
->GetBackingPixmap(),(GC
) m_gcBacking
, x
, y
, w
, h
);
1467 m_brush
= saveBrush
;
1470 void wxWindowDC::SetFont( const wxFont
&font
)
1472 wxCHECK_RET( Ok(), "invalid dc" );
1478 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1480 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1482 if (m_window
&& m_window
->GetBackingPixmap())
1483 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, (Font
) m_oldFont
);
1488 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1490 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1491 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1493 if (m_window
&& m_window
->GetBackingPixmap())
1494 XSetFont ((Display
*) m_display
,(GC
) m_gcBacking
, fontId
);
1497 void wxWindowDC::SetPen( const wxPen
&pen
)
1499 wxCHECK_RET( Ok(), "invalid dc" );
1505 wxBitmap oldStipple
= m_currentStipple
;
1506 int oldStyle
= m_currentStyle
;
1507 int oldFill
= m_currentFill
;
1508 int old_pen_width
= m_currentPenWidth
;
1509 int old_pen_join
= m_currentPenJoin
;
1510 int old_pen_cap
= m_currentPenCap
;
1511 int old_pen_nb_dash
= m_currentPenDashCount
;
1512 char *old_pen_dash
= m_currentPenDash
;
1514 wxColour oldPenColour
= m_currentColour
;
1515 m_currentColour
= m_pen
.GetColour ();
1516 m_currentStyle
= m_pen
.GetStyle ();
1517 m_currentFill
= m_pen
.GetStyle (); // TODO?
1518 m_currentPenWidth
= m_pen
.GetWidth ();
1519 m_currentPenJoin
= m_pen
.GetJoin ();
1520 m_currentPenCap
= m_pen
.GetCap ();
1521 m_currentPenDashCount
= m_pen
.GetDashCount();
1522 m_currentPenDash
= m_pen
.GetDash();
1524 if (m_currentStyle
== wxSTIPPLE
)
1525 m_currentStipple
= * m_pen
.GetStipple ();
1527 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1528 oldFill
== m_currentFill
&&
1529 old_pen_join
== m_currentPenJoin
&&
1530 old_pen_cap
== m_currentPenCap
&&
1531 old_pen_nb_dash
== m_currentPenDashCount
&&
1532 old_pen_dash
== m_currentPenDash
&&
1533 old_pen_width
== m_currentPenWidth
);
1535 bool sameColour
= (oldPenColour
.Ok () &&
1536 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1537 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1538 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1539 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1541 if (!sameStyle
|| !GetOptimization())
1543 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1544 if (scaled_width
< 0)
1550 static const char dotted
[] = {2, 5};
1551 static const char short_dashed
[] = {4, 4};
1552 static const char long_dashed
[] = {4, 8};
1553 static const char dotted_dashed
[] = {6, 6, 2, 6};
1555 // We express dash pattern in pen width unit, so we are
1556 // independent of zoom factor and so on...
1558 const char *req_dash
;
1560 switch (m_pen
.GetStyle ())
1563 req_nb_dash
= m_currentPenDashCount
;
1564 req_dash
= m_currentPenDash
;
1565 style
= LineOnOffDash
;
1570 style
= LineOnOffDash
;
1574 req_dash
= short_dashed
;
1575 style
= LineOnOffDash
;
1579 req_dash
= long_dashed
;
1580 style
= LineOnOffDash
;
1584 req_dash
= dotted_dashed
;
1585 style
= LineOnOffDash
;
1596 if (req_dash
&& req_nb_dash
)
1598 char *real_req_dash
= new char[req_nb_dash
];
1601 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1602 for (int i
= 0; i
< req_nb_dash
; i
++)
1603 real_req_dash
[i
] = req_dash
[i
] * factor
;
1604 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1606 if (m_window
&& m_window
->GetBackingPixmap())
1607 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, real_req_dash
, req_nb_dash
);
1608 delete[]real_req_dash
;
1612 // No Memory. We use non-scaled dash pattern...
1613 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1615 if (m_window
&& m_window
->GetBackingPixmap())
1616 XSetDashes ((Display
*) m_display
,(GC
) m_gcBacking
, 0, req_dash
, req_nb_dash
);
1620 switch (m_pen
.GetCap ())
1622 case wxCAP_PROJECTING
:
1623 cap
= CapProjecting
;
1630 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1634 switch (m_pen
.GetJoin ())
1648 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1650 if (m_window
&& m_window
->GetBackingPixmap())
1651 XSetLineAttributes ((Display
*) m_display
,(GC
) m_gcBacking
, scaled_width
, style
, cap
, join
);
1654 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1658 oldStipple
= wxNullBitmap
; // For later reset!!
1660 switch (m_currentFill
)
1662 case wxBDIAGONAL_HATCH
:
1663 if (bdiag
== (Pixmap
) 0)
1664 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1665 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1666 bdiag_bits
, bdiag_width
, bdiag_height
);
1669 case wxFDIAGONAL_HATCH
:
1670 if (fdiag
== (Pixmap
) 0)
1671 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1672 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1673 fdiag_bits
, fdiag_width
, fdiag_height
);
1677 if (cross
== (Pixmap
) 0)
1678 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1679 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1680 cross_bits
, cross_width
, cross_height
);
1683 case wxHORIZONTAL_HATCH
:
1684 if (horiz
== (Pixmap
) 0)
1685 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1686 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1687 horiz_bits
, horiz_width
, horiz_height
);
1690 case wxVERTICAL_HATCH
:
1691 if (verti
== (Pixmap
) 0)
1692 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1693 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1694 verti_bits
, verti_width
, verti_height
);
1697 case wxCROSSDIAG_HATCH
:
1699 if (cdiag
== (Pixmap
) 0)
1700 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1701 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1702 cdiag_bits
, cdiag_width
, cdiag_height
);
1706 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1708 if (m_window
&& m_window
->GetBackingPixmap())
1709 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1711 else if (m_currentStipple
.Ok()
1712 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1714 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1716 if (m_window
&& m_window
->GetBackingPixmap())
1717 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1720 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1724 if (m_currentFill
== wxSTIPPLE
)
1725 fill_style
= FillStippled
;
1726 else if (IS_HATCH (m_currentFill
))
1727 fill_style
= FillStippled
;
1729 fill_style
= FillSolid
;
1730 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1731 if (m_window
&& m_window
->GetBackingPixmap())
1732 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, fill_style
);
1735 // must test m_logicalFunction, because it involves background!
1736 if (!sameColour
|| !GetOptimization()
1737 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1740 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1741 pixel
= m_backgroundPixel
;
1744 unsigned char red
= m_pen
.GetColour ().Red ();
1745 unsigned char blue
= m_pen
.GetColour ().Blue ();
1746 unsigned char green
= m_pen
.GetColour ().Green ();
1747 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1748 && green
== (unsigned char) 255)
1750 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1751 m_currentColour
= *wxWHITE
;
1752 m_pen
.GetColour().SetPixel(pixel
);
1753 m_currentColour
.SetPixel(pixel
);
1757 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1758 m_currentColour
= *wxBLACK
;
1759 m_pen
.GetColour().SetPixel(pixel
);
1764 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1765 m_currentColour
.SetPixel(pixel
);
1768 // Finally, set the GC to the required colour
1771 if (m_logicalFunction
== wxXOR
)
1774 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1775 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1776 if (m_window
&& m_window
->GetBackingPixmap())
1777 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1781 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1782 if (m_window
&& m_window
->GetBackingPixmap())
1783 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1788 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1793 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1795 wxCHECK_RET( Ok(), "invalid dc" );
1799 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1802 int oldFill
= m_currentFill
;
1803 wxBitmap oldStipple
= m_currentStipple
;
1805 m_autoSetting
|= 0x1;
1807 m_currentFill
= m_brush
.GetStyle ();
1808 if (m_currentFill
== wxSTIPPLE
)
1809 m_currentStipple
= * m_brush
.GetStipple ();
1811 wxColour
oldBrushColour(m_currentColour
);
1812 m_currentColour
= m_brush
.GetColour ();
1814 bool sameColour
= (oldBrushColour
.Ok () &&
1815 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1816 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1817 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1818 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1820 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1822 switch (brush
.GetStyle ())
1826 case wxBDIAGONAL_HATCH
:
1827 case wxCROSSDIAG_HATCH
:
1828 case wxFDIAGONAL_HATCH
:
1830 case wxHORIZONTAL_HATCH
:
1831 case wxVERTICAL_HATCH
:
1834 // Chris Breeze 23/07/97: use background mode to determine whether
1835 // fill style should be solid or transparent
1836 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1837 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1838 if (m_window
&& m_window
->GetBackingPixmap())
1839 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, style
);
1844 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1845 if (m_window
&& m_window
->GetBackingPixmap())
1846 XSetFillStyle ((Display
*) m_display
,(GC
) m_gcBacking
, FillSolid
);
1850 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1854 switch (m_currentFill
)
1856 case wxBDIAGONAL_HATCH
:
1857 if (bdiag
== (Pixmap
) 0)
1858 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1859 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1860 bdiag_bits
, bdiag_width
, bdiag_height
);
1863 case wxFDIAGONAL_HATCH
:
1864 if (fdiag
== (Pixmap
) 0)
1865 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1866 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1867 fdiag_bits
, fdiag_width
, fdiag_height
);
1871 if (cross
== (Pixmap
) 0)
1872 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1873 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1874 cross_bits
, cross_width
, cross_height
);
1877 case wxHORIZONTAL_HATCH
:
1878 if (horiz
== (Pixmap
) 0)
1879 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1880 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1881 horiz_bits
, horiz_width
, horiz_height
);
1884 case wxVERTICAL_HATCH
:
1885 if (verti
== (Pixmap
) 0)
1886 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1887 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1888 verti_bits
, verti_width
, verti_height
);
1891 case wxCROSSDIAG_HATCH
:
1893 if (cdiag
== (Pixmap
) 0)
1894 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1895 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1896 cdiag_bits
, cdiag_width
, cdiag_height
);
1900 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1902 if (m_window
&& m_window
->GetBackingPixmap())
1903 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, myStipple
);
1905 // X can forget the stipple value when resizing a window (apparently)
1906 // so always set the stipple.
1907 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1909 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1910 if (m_window
&& m_window
->GetBackingPixmap())
1911 XSetStipple ((Display
*) m_display
,(GC
) m_gcBacking
, (Pixmap
) m_currentStipple
.GetPixmap());
1914 // must test m_logicalFunction, because it involves background!
1915 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1920 // Policy - on a monochrome screen, all brushes are white,
1921 // except when they're REALLY black!!!
1922 unsigned char red
= m_brush
.GetColour ().Red ();
1923 unsigned char blue
= m_brush
.GetColour ().Blue ();
1924 unsigned char green
= m_brush
.GetColour ().Green ();
1926 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1927 && green
== (unsigned char) 0)
1929 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1930 m_currentColour
= *wxBLACK
;
1931 m_brush
.GetColour().SetPixel(pixel
);
1932 m_currentColour
.SetPixel(pixel
);
1936 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1937 m_currentColour
= *wxWHITE
;
1938 m_brush
.GetColour().SetPixel(pixel
);
1939 m_currentColour
.SetPixel(pixel
);
1942 // N.B. comment out the above line and uncomment the following lines
1943 // if you want non-white colours to be black on a monochrome display.
1945 if (red == (unsigned char )255 && blue == (unsigned char)255
1946 && green == (unsigned char)255)
1947 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1949 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1952 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1954 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1955 m_currentColour
.SetPixel(pixel
);
1959 // Finally, set the GC to the required colour
1960 if (m_logicalFunction
== wxXOR
)
1963 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1964 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1965 if (m_window
&& m_window
->GetBackingPixmap())
1966 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
^ values
.background
);
1970 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1971 if (m_window
&& m_window
->GetBackingPixmap())
1972 XSetForeground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
1977 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1980 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1982 wxCHECK_RET( Ok(), "invalid dc" );
1984 m_backgroundBrush
= brush
;
1986 if (!m_backgroundBrush
.Ok())
1989 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1991 // New behaviour, 10/2/99: setting the background brush of a DC
1992 // doesn't affect the window background colour.
1994 // XSetWindowBackground doesn't work for non-Window pixmaps
1995 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1996 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1999 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2000 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2001 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
2002 if (m_window
&& m_window
->GetBackingPixmap())
2003 XSetBackground ((Display
*) m_display
,(GC
) m_gcBacking
, pixel
);
2006 void wxWindowDC::SetLogicalFunction( int function
)
2008 wxCHECK_RET( Ok(), "invalid dc" );
2013 if (m_logicalFunction
== function
)
2019 x_function
= GXclear
;
2025 x_function
= GXinvert
;
2028 x_function
= GXorReverse
;
2031 x_function
= GXandReverse
;
2040 x_function
= GXandInverted
;
2043 x_function
= GXnoop
;
2049 x_function
= GXequiv
;
2052 x_function
= GXcopyInverted
;
2055 x_function
= GXorInverted
;
2058 x_function
= GXnand
;
2065 x_function
= GXcopy
;
2069 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
2070 if (m_window
&& m_window
->GetBackingPixmap())
2071 XSetFunction((Display
*) m_display
, (GC
) m_gcBacking
, x_function
);
2073 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
2074 /* MATTHEW: [9] Need to redo pen simply */
2075 m_autoSetting
|= 0x2;
2077 m_logicalFunction
= function
;
2081 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2083 wxCHECK_RET( Ok(), "invalid dc" );
2085 if (m_textForegroundColour
== col
)
2088 m_textForegroundColour
= col
;
2092 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2094 wxCHECK_RET( Ok(), "invalid dc" );
2096 if (m_textBackgroundColour
== col
)
2099 m_textBackgroundColour
= col
;
2100 if (!m_textBackgroundColour
.Ok())
2104 void wxWindowDC::SetBackgroundMode( int mode
)
2106 m_backgroundMode
= mode
;
2109 void wxWindowDC::SetPalette( const wxPalette
& palette
)
2114 /* Use GetXColormap */
2115 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2116 (Colormap
) palette
.GetXColormap());
2118 /* Use wxGetMainColormap */
2119 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
2120 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
2125 void wxWindowDC::SetDCClipping()
2127 // m_userRegion is the region set by calling SetClippingRegion
2129 if (m_currentRegion
)
2130 XDestroyRegion ((Region
) m_currentRegion
);
2132 // We need to take into account
2133 // clipping imposed on a window by a repaint.
2134 // We'll combine it with the user region. But for now,
2135 // just use the currently-defined user clipping region.
2136 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
2137 m_currentRegion
= (WXRegion
) XCreateRegion ();
2139 m_currentRegion
= (WXRegion
) NULL
;
2141 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
2142 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
2143 else if (m_userRegion
)
2144 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
2145 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
2146 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetXRegion(), (Region
) m_window
->GetUpdateRegion().GetXRegion(),
2147 (Region
) m_currentRegion
);
2149 if (m_currentRegion
)
2151 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
2155 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2160 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2162 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
2165 XDestroyRegion ((Region
) m_userRegion
);
2166 m_userRegion
= (WXRegion
) XCreateRegion ();
2170 r
.width
= XLOG2DEVREL(width
);
2171 r
.height
= YLOG2DEVREL(height
);
2172 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
2176 // Needs to work differently for Pixmap: without this,
2177 // there's a nasty (Display*) m_display bug. 8/12/94
2178 if (m_window
&& m_window
->GetBackingPixmap())
2180 XRectangle rects
[1];
2181 rects
[0].x
= XLOG2DEV_2(x
);
2182 rects
[0].y
= YLOG2DEV_2(y
);
2183 rects
[0].width
= XLOG2DEVREL(width
);
2184 rects
[0].height
= YLOG2DEVREL(height
);
2185 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2189 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
2191 wxRect box
= region
.GetBox();
2193 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
2196 XDestroyRegion ((Region
) m_userRegion
);
2197 m_userRegion
= (WXRegion
) XCreateRegion ();
2199 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetXRegion(), (Region
) m_userRegion
);
2203 // Needs to work differently for Pixmap: without this,
2204 // there's a nasty (Display*) m_display bug. 8/12/94
2205 if (m_window
&& m_window
->GetBackingPixmap())
2207 XRectangle rects
[1];
2208 rects
[0].x
= XLOG2DEV_2(box
.x
);
2209 rects
[0].y
= YLOG2DEV_2(box
.y
);
2210 rects
[0].width
= XLOG2DEVREL(box
.width
);
2211 rects
[0].height
= YLOG2DEVREL(box
.height
);
2212 XSetClipRectangles((Display
*) m_display
, (GC
) m_gcBacking
, 0, 0, rects
, 1, Unsorted
);
2217 void wxWindowDC::DestroyClippingRegion()
2219 wxDC::DestroyClippingRegion();
2222 XDestroyRegion ((Region
) m_userRegion
);
2223 m_userRegion
= NULL
;
2228 gc_val
.clip_mask
= None
;
2229 if (m_window
&& m_window
->GetBackingPixmap())
2230 XChangeGC((Display
*) m_display
, (GC
) m_gcBacking
, GCClipMask
, &gc_val
);
2233 // Resolution in pixels per logical inch
2234 wxSize
wxWindowDC::GetPPI() const
2236 return wxSize(100, 100);
2239 int wxWindowDC::GetDepth() const
2246 // ----------------------------------- spline code ----------------------------------------
2248 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
2249 double a3
, double b3
, double a4
, double b4
);
2250 void wx_clear_stack();
2251 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
2252 double *y3
, double *x4
, double *y4
);
2253 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
2254 double x4
, double y4
);
2255 static bool wx_spline_add_point(double x
, double y
);
2256 static void wx_spline_draw_point_array(wxDC
*dc
);
2258 wxList wx_spline_point_list
;
2260 #define half(z1, z2) ((z1+z2)/2.0)
2263 /* iterative version */
2265 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
2268 register double xmid
, ymid
;
2269 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2272 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
2274 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
2275 xmid
= (double)half(x2
, x3
);
2276 ymid
= (double)half(y2
, y3
);
2277 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
2278 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
2279 wx_spline_add_point( x1
, y1
);
2280 wx_spline_add_point( xmid
, ymid
);
2282 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
2283 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
2284 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
2285 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
2290 /* utilities used by spline drawing routines */
2292 typedef struct wx_spline_stack_struct
{
2293 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
2296 #define SPLINE_STACK_DEPTH 20
2297 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
2298 static Stack
*wx_stack_top
;
2299 static int wx_stack_count
;
2301 void wx_clear_stack()
2303 wx_stack_top
= wx_spline_stack
;
2307 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
2309 wx_stack_top
->x1
= x1
;
2310 wx_stack_top
->y1
= y1
;
2311 wx_stack_top
->x2
= x2
;
2312 wx_stack_top
->y2
= y2
;
2313 wx_stack_top
->x3
= x3
;
2314 wx_stack_top
->y3
= y3
;
2315 wx_stack_top
->x4
= x4
;
2316 wx_stack_top
->y4
= y4
;
2321 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
2322 double *x3
, double *y3
, double *x4
, double *y4
)
2324 if (wx_stack_count
== 0)
2328 *x1
= wx_stack_top
->x1
;
2329 *y1
= wx_stack_top
->y1
;
2330 *x2
= wx_stack_top
->x2
;
2331 *y2
= wx_stack_top
->y2
;
2332 *x3
= wx_stack_top
->x3
;
2333 *y3
= wx_stack_top
->y3
;
2334 *x4
= wx_stack_top
->x4
;
2335 *y4
= wx_stack_top
->y4
;
2339 static bool wx_spline_add_point(double x
, double y
)
2341 wxPoint
*point
= new wxPoint
;
2344 wx_spline_point_list
.Append((wxObject
*)point
);
2348 static void wx_spline_draw_point_array(wxDC
*dc
)
2350 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
2351 wxNode
*node
= wx_spline_point_list
.First();
2354 wxPoint
*point
= (wxPoint
*)node
->Data();
2357 node
= wx_spline_point_list
.First();
2361 void wxWindowDC::DoDrawSpline( wxList
*points
)
2363 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2366 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
2367 double x1
, y1
, x2
, y2
;
2369 wxNode
*node
= points
->First();
2370 p
= (wxPoint
*)node
->Data();
2375 node
= node
->Next();
2376 p
= (wxPoint
*)node
->Data();
2380 cx1
= (double)((x1
+ x2
) / 2);
2381 cy1
= (double)((y1
+ y2
) / 2);
2382 cx2
= (double)((cx1
+ x2
) / 2);
2383 cy2
= (double)((cy1
+ y2
) / 2);
2385 wx_spline_add_point(x1
, y1
);
2387 while ((node
= node
->Next()) != NULL
)
2389 p
= (wxPoint
*)node
->Data();
2394 cx4
= (double)(x1
+ x2
) / 2;
2395 cy4
= (double)(y1
+ y2
) / 2;
2396 cx3
= (double)(x1
+ cx4
) / 2;
2397 cy3
= (double)(y1
+ cy4
) / 2;
2399 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
2403 cx2
= (double)(cx1
+ x2
) / 2;
2404 cy2
= (double)(cy1
+ y2
) / 2;
2407 wx_spline_add_point( cx1
, cy1
);
2408 wx_spline_add_point( x2
, y2
);
2410 wx_spline_draw_point_array( this );
2413 #endif // wxUSE_SPLINE
2417 // ----------------------------------------------------------------------------
2419 // ----------------------------------------------------------------------------
2421 wxPaintDC::wxPaintDC(wxWindow
* win
) : wxWindowDC(win
)
2423 wxRegion
* region
= NULL
;
2425 // Combine all the update rects into a region
2426 const wxRectList
& updateRects(win
->GetUpdateRects());
2427 if ( updateRects
.GetCount() != 0 )
2429 for ( wxRectList::Node
*node
= updateRects
.GetFirst();
2431 node
= node
->GetNext() )
2433 wxRect
* rect
= node
->GetData();
2436 region
= new wxRegion(*rect
);
2438 // TODO: is this correct? In SetDCClipping above,
2439 // XIntersectRegion is used to combine paint and user
2440 // regions. XIntersectRegion appears to work in that case...
2441 region
->Union(*rect
);
2447 win
->GetClientSize(&cw
, &ch
);
2448 region
= new wxRegion(wxRect(0, 0, cw
, ch
));
2451 win
->SetUpdateRegion(*region
);
2453 wxRegion
& theRegion(win
->GetUpdateRegion());
2454 theRegion
.SetRects(updateRects
); // We also store in terms of rects, for iteration to work.
2456 // Set the clipping region. Any user-defined region will be combined with this
2457 // one in SetDCClipping.
2458 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) region
->GetXRegion());
2463 wxPaintDC::~wxPaintDC()
2465 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
2467 m_window
->ClearUpdateRegion();
2470 // ----------------------------------------------------------------------------
2471 // private functions
2472 // ----------------------------------------------------------------------------
2475 Used when copying between drawables on different (Display*) m_displays. Not
2476 very fast, but better than giving up.
2479 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2480 Drawable src
, Drawable dest
,
2483 unsigned int w
, unsigned int h
,
2484 int destx
, int desty
,
2485 bool more
, XImage
**cache
)
2487 XImage
*image
, *destimage
;
2488 Colormap destcm
, srccm
;
2489 static const int CACHE_SIZE
= 256;
2492 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2493 int k
, cache_pos
, all_cache
;
2495 if (!cache
|| !*cache
)
2496 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2500 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2502 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2503 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2508 for (i
= 0; i
< w
; i
++)
2509 for (j
= 0; j
< h
; j
++) {
2510 unsigned long pixel
;
2513 pixel
= XGetPixel(image
, i
, j
);
2514 for (k
= cache_pos
; k
--; )
2515 if (cachesrc
[k
] == pixel
) {
2516 pixel
= cachedest
[k
];
2520 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2521 if (cachesrc
[k
] == pixel
) {
2522 pixel
= cachedest
[k
];
2526 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2527 XQueryColor(src_display
, srccm
, &xcol
);
2528 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2530 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2532 if (++cache_pos
>= CACHE_SIZE
) {
2538 XPutPixel(destimage
, i
, j
, pixel
);
2541 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2542 XDestroyImage(destimage
);
2547 XDestroyImage(image
);
2552 /* Helper function for 16-bit fonts */
2553 static int str16len(const char *s
)
2557 while (s
[0] && s
[1]) {