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
55 #include "X11/Xutil.h"
57 #pragma message enable nosimpint
60 #include "wx/x11/private.h"
63 #include <float.h> // for M_PI
73 static Pixmap bdiag
, cdiag
, fdiag
, cross
, horiz
, verti
;
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
79 // Fudge factor (VZ: what??)
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
87 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
88 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
95 Drawable src
, Drawable dest
,
98 unsigned int w
, unsigned int h
,
100 bool more
, XImage
**cache
);
102 // ============================================================================
104 // ============================================================================
107 * compare two doubles and return the larger rounded
110 static int roundmax(double a
, double b
)
112 return (int)((a
> b
? a
: b
) + 0.5);
116 * compare two doubles and return the smaller rounded
119 static int roundmin(double a
, double b
)
121 return (int)((a
< b
? a
: b
) - 0.5);
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
129 wxWindowDC::wxWindowDC()
132 m_gcBacking
= (WXGC
) 0;
134 m_backgroundPixel
= -1;
135 m_currentPenWidth
= 1;
136 m_currentPenJoin
= -1;
137 m_currentPenDashCount
= -1;
138 m_currentPenDash
= (wxX11Dash
*) NULL
;
141 // m_currentBkMode = wxTRANSPARENT;
142 m_colour
= wxColourDisplay();
143 m_display
= (WXDisplay
*) NULL
;
144 m_currentRegion
= (WXRegion
) 0;
145 m_userRegion
= (WXRegion
) 0;
146 m_pixmap
= (WXPixmap
) 0;
148 m_oldFont
= (WXFont
) 0;
151 wxWindowDC::wxWindowDC( wxWindow
*window
)
153 wxASSERT_MSG( (window
!= (wxWindow
*) NULL
), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
156 m_font
= window
->GetFont();
158 m_gcBacking
= (WXGC
) 0;
159 m_backgroundPixel
= -1;
160 m_currentPenWidth
= 1;
161 m_currentPenJoin
= -1;
162 m_currentPenDashCount
= -1;
163 m_currentPenDash
= (wxX11Dash
*) NULL
;
166 // m_currentBkMode = wxTRANSPARENT;
167 m_colour
= wxColourDisplay();
168 m_currentRegion
= (WXRegion
) 0;
169 m_userRegion
= (WXRegion
) 0;
173 m_display
= window
->GetXDisplay();
174 m_pixmap
= window
->GetXWindow();
175 Display
* display
= (Display
*) m_display
;
177 XSetWindowColormap (display
, (Pixmap
) m_pixmap
, (Colormap
) wxTheApp
->GetMainColormap(m_display
));
180 gcvalues
.foreground
= BlackPixel (display
, DefaultScreen (display
));
181 gcvalues
.background
= WhitePixel (display
, DefaultScreen (display
));
182 gcvalues
.graphics_exposures
= False
;
183 gcvalues
.subwindow_mode
= IncludeInferiors
;
184 gcvalues
.line_width
= 1;
185 m_gc
= (WXGC
) XCreateGC (display
, RootWindow (display
, DefaultScreen (display
)),
186 GCForeground
| GCBackground
| GCGraphicsExposures
| GCLineWidth
| GCSubwindowMode
,
189 m_backgroundPixel
= (int) gcvalues
.background
;
191 // Get the current Font so we can set it back later
193 XGetGCValues((Display
*) m_display
, (GC
) m_gc
, GCFont
, &valReturn
);
194 m_oldFont
= (WXFont
) valReturn
.font
;
196 SetBackground(wxBrush(m_window
->GetBackgroundColour(), wxSOLID
));
199 wxWindowDC::~wxWindowDC()
201 if (m_gc
&& (m_oldFont
!= (WXFont
) 0) && ((long) m_oldFont
!= -1))
203 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
207 XFreeGC ((Display
*) m_display
, (GC
) m_gc
);
211 XFreeGC ((Display
*) m_display
, (GC
) m_gcBacking
);
212 m_gcBacking
= (WXGC
) 0;
215 XDestroyRegion ((Region
) m_currentRegion
);
216 m_currentRegion
= (WXRegion
) 0;
219 XDestroyRegion ((Region
) m_userRegion
);
220 m_userRegion
= (WXRegion
) 0;
223 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
224 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
226 wxFAIL_MSG("not implemented");
229 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
231 // Generic (and therefore rather inefficient) method.
232 // Could be improved.
234 wxBitmap
bitmap(1, 1);
235 memdc
.SelectObject(bitmap
);
236 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
237 memdc
.SelectObject(wxNullBitmap
);
238 wxImage
image(bitmap
);
239 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
243 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
245 wxCHECK_RET( Ok(), "invalid dc" );
247 int x1d
, y1d
, x2d
, y2d
;
249 // FreeGetPixelCache();
259 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x1d
, y1d
, x2d
, y2d
);
261 CalcBoundingBox(x1
, y1
);
262 CalcBoundingBox(x2
, y2
);
265 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
267 wxCHECK_RET( Ok(), "invalid dc" );
272 int xx
= XLOG2DEV (x
);
273 int yy
= YLOG2DEV (y
);
275 wxDisplaySize (&ww
, &hh
);
276 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, yy
,
278 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xx
, 0,
282 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
284 wxCHECK_RET( Ok(), "invalid dc" );
286 // FreeGetPixelCache();
288 int xx1
= XLOG2DEV (x1
);
289 int yy1
= YLOG2DEV (y1
);
290 int xx2
= XLOG2DEV (x2
);
291 int yy2
= YLOG2DEV (y2
);
292 int xxc
= XLOG2DEV (xc
);
293 int yyc
= YLOG2DEV (yc
);
294 int xxc_2
= XLOG2DEV_2 (xc
);
295 int yyc_2
= YLOG2DEV_2 (yc
);
297 wxCoord dx
= xx1
- xxc
;
298 wxCoord dy
= yy1
- yyc
;
299 double radius
= sqrt ((double)(dx
* dx
+ dy
* dy
));
300 wxCoord r
= (wxCoord
) radius
;
302 double radius1
, radius2
;
304 if (xx1
== xx2
&& yy1
== yy2
)
309 else if (radius
== 0.0)
310 radius1
= radius2
= 0.0;
319 radius1
= -atan2 ((double) (yy1
- yyc
), (double) (xx1
- xxc
)) * 360.0 / (2 * M_PI
);
327 radius2
= -atan2 ((double) (yy2
- yyc
), (double) (xx2
- xxc
)) * 360.0 / (2 * M_PI
);
331 int alpha1
= (int) radius1
;
332 int alpha2
= (int) (radius2
- radius1
);
335 while (alpha2
> 360 * 64)
338 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
341 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) (GC
) m_gc
,
342 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
346 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
350 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
351 xxc
- r
, yyc
- r
, 2 * r
, 2 * r
, alpha1
, alpha2
);
353 CalcBoundingBox (x1
, y1
);
354 CalcBoundingBox (x2
, y2
);
357 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
359 wxCHECK_RET( Ok(), "invalid dc" );
365 wd
= XLOG2DEVREL(width
);
366 hd
= YLOG2DEVREL(height
);
368 if (sa
>=360 || sa
<=-360) sa
=sa
-int(sa
/360)*360;
369 if (ea
>=360 || ea
<=-360) ea
=ea
-int(ea
/360)*360;
370 int start
= int(sa
*64);
371 int end
= int(ea
*64);
372 if (start
<0) start
+=360*64;
373 if (end
<0) end
+=360*64;
374 if (end
>start
) end
-=start
;
375 else end
+=360*64-start
;
377 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
379 m_autoSetting
= TRUE
; // must be reset
382 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
, end
);
385 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
389 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, start
,end
);
392 CalcBoundingBox (x
, y
);
393 CalcBoundingBox (x
+ width
, y
+ height
);
396 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
398 wxCHECK_RET( Ok(), "invalid dc" );
400 // FreeGetPixelCache();
402 if (m_pen
.Ok() && m_autoSetting
)
405 XDrawPoint ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
));
407 CalcBoundingBox (x
, y
);
410 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
412 wxCHECK_RET( Ok(), "invalid dc" );
414 // FreeGetPixelCache();
416 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
421 XPoint
*xpoints
= new XPoint
[n
];
424 for (i
= 0; i
< n
; i
++)
426 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
427 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
429 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints
, n
, 0);
435 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
436 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
438 wxCHECK_RET( Ok(), "invalid dc" );
440 // FreeGetPixelCache();
442 XPoint
*xpoints1
= new XPoint
[n
+ 1];
443 XPoint
*xpoints2
= new XPoint
[n
+ 1];
445 for (i
= 0; i
< n
; i
++)
447 xpoints1
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
448 xpoints1
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
449 xpoints2
[i
].x
= XLOG2DEV_2 (points
[i
].x
+ xoffset
);
450 xpoints2
[i
].y
= YLOG2DEV_2 (points
[i
].y
+ yoffset
);
451 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
454 // Close figure for XDrawLines (not needed for XFillPolygon)
455 xpoints1
[i
].x
= xpoints1
[0].x
;
456 xpoints1
[i
].y
= xpoints1
[0].y
;
457 xpoints2
[i
].x
= xpoints2
[0].x
;
458 xpoints2
[i
].y
= xpoints2
[0].y
;
460 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
463 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, fillStyle
== wxODDEVEN_RULE
? EvenOddRule
: WindingRule
);
464 XFillPolygon ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
, Complex
, 0);
465 XSetFillRule ((Display
*) m_display
, (GC
) m_gc
, EvenOddRule
); // default mode
468 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
472 XDrawLines ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xpoints1
, n
+ 1, 0);
479 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
481 wxCHECK_RET( Ok(), "invalid dc" );
483 // FreeGetPixelCache();
485 int xd
, yd
, wfd
, hfd
, wd
, hd
;
489 wfd
= XLOG2DEVREL(width
);
491 hfd
= YLOG2DEVREL(height
);
494 if (wfd
== 0 || hfd
== 0) return;
495 if (wd
< 0) { wd
= - wd
; xd
= xd
- wd
; }
496 if (hd
< 0) { hd
= - hd
; yd
= yd
- hd
; }
498 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
501 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wfd
, hfd
);
504 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
508 XDrawRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
);
511 CalcBoundingBox (x
, y
);
512 CalcBoundingBox (x
+ width
, y
+ height
);
515 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
517 wxCHECK_RET( Ok(), "invalid dc" );
519 // FreeGetPixelCache();
521 // If radius is negative, it's a proportion of the smaller dimension.
523 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
525 int xd
= XLOG2DEV (x
);
526 int yd
= YLOG2DEV (y
);
527 int rd
= XLOG2DEVREL ((long) radius
);
528 int wd
= XLOG2DEVREL (width
) - WX_GC_CF
;
529 int hd
= YLOG2DEVREL (height
) - WX_GC_CF
;
534 // If radius is zero use DrawRectangle() instead to avoid
535 // X drawing errors with small radii
538 DrawRectangle( x
, y
, width
, height
);
542 // Draw nothing if transformed w or h is 0
543 if (wd
== 0 || hd
== 0) return;
545 // CMB: adjust size if outline is drawn otherwise the result is
546 // 1 pixel too wide and high
547 if (m_pen
.GetStyle() != wxTRANSPARENT
)
553 // CMB: ensure dd is not larger than rectangle otherwise we
554 // get an hour glass shape
555 if (rw_d
> wd
) rw_d
= wd
;
556 if (rw_d
> hd
) rw_d
= hd
;
559 // For backing pixmap
560 int xd2
= XLOG2DEV_2 (x
);
561 int yd2
= YLOG2DEV_2 (y
);
562 int rd2
= XLOG2DEVREL ((long) radius
);
563 int wd2
= XLOG2DEVREL (width
) ;
564 int hd2
= YLOG2DEVREL (height
) ;
569 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
573 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
575 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
578 // Arcs start from 3 o'clock, positive angles anticlockwise
580 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
581 rw_d
, rh_d
, 90 * 64, 90 * 64);
583 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
584 // rw_d, rh_d, 0, 90 * 64);
585 rw_d
, rh_d
, 0, 91 * 64);
587 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
589 // rw_d, rh_d, 270 * 64, 90 * 64);
590 rw_d
, rh_d
, 269 * 64, 92 * 64);
592 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
593 rw_d
, rh_d
, 180 * 64, 90 * 64);
596 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
599 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
,
600 xd
+ wd
- rd
+ 1, yd
);
601 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ rd
, yd
+ hd
,
602 xd
+ wd
- rd
, yd
+ hd
);
604 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ rd
,
606 XDrawLine ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
, yd
+ rd
,
607 xd
+ wd
, yd
+ hd
- rd
+ 1);
608 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
,
609 rw_d
, rh_d
, 90 * 64, 90 * 64);
610 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
, yd
,
611 // rw_d, rh_d, 0, 90 * 64);
612 rw_d
, rh_d
, 0, 91 * 64);
613 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
+ wd
- rw_d
,
615 rw_d
, rh_d
, 269 * 64, 92 * 64);
616 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
+ hd
- rh_d
,
617 rw_d
, rh_d
, 180 * 64, 90 * 64);
619 CalcBoundingBox (x
, y
);
620 CalcBoundingBox (x
+ width
, y
+ height
);
625 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
627 wxCHECK_RET( Ok(), "invalid dc" );
629 // Check for negative width and height
642 // FreeGetPixelCache();
644 static const int angle
= 23040;
650 wd
= XLOG2DEVREL(width
) ;
651 hd
= YLOG2DEVREL(height
) ;
653 if (m_brush
.Ok() && m_brush
.GetStyle () != wxTRANSPARENT
)
656 XFillArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
659 if (m_pen
.Ok() && m_pen
.GetStyle () != wxTRANSPARENT
)
663 XDrawArc ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, xd
, yd
, wd
, hd
, 0, angle
);
665 CalcBoundingBox (x
, y
);
666 CalcBoundingBox (x
+ width
, y
+ height
);
670 bool wxWindowDC::CanDrawBitmap() const
672 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
678 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
680 // FreeGetPixelCache();
682 // Be sure that foreground pixels (1) of
683 // the Icon will be painted with pen colour. [m_pen.SetColour()]
684 // Background pixels (0) will be painted with
685 // last selected background color. [::SetBackground]
686 if (m_pen
.Ok() && m_autoSetting
)
690 Pixmap iconPixmap
= (Pixmap
) icon
.GetPixmap();
691 width
= icon
.GetWidth();
692 height
= icon
.GetHeight();
693 if (icon
.GetDisplay() == m_display
)
695 if (icon
.GetDepth() <= 1)
697 XCopyPlane ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
699 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), 1);
703 XCopyArea ((Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
705 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
));
708 } else { /* Remote copy (different (Display*) m_displays) */
709 XImage
*cache
= NULL
;
710 if (m_window
&& m_window
->GetBackingPixmap())
711 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
712 (GC
) m_gcBacking
, 0, 0, width
, height
,
713 (int) XLOG2DEV_2 (x
), (int) YLOG2DEV_2 (y
), TRUE
, &cache
);
714 XCopyRemote((Display
*) icon
.GetDisplay(), (Display
*) m_display
, iconPixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
716 (int) XLOG2DEV (x
), (int) YLOG2DEV (y
), FALSE
, &cache
);
718 CalcBoundingBox (x
, y
);
722 // TODO: use scaled Blit e.g. as per John Price's implementation in Contrib/Utilities
723 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
724 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
725 wxCoord xsrcMask
, wxCoord ysrcMask
)
727 wxCHECK_MSG( Ok(), FALSE
, "invalid dc" );
729 wxWindowDC
* sourceDC
= wxDynamicCast(source
, wxWindowDC
);
731 wxASSERT_MSG( sourceDC
, "Blit source DC must be wxWindowDC or derived class." );
733 // FreeGetPixelCache();
735 // Be sure that foreground pixels (1) of the Icon will be painted with pen
736 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
737 // last selected background color. [::SetBackground]
738 if (m_pen
.Ok() && m_autoSetting
)
741 // Do bitmap scaling if necessary
743 wxBitmap
*scaledBitmap
= (wxBitmap
*) NULL
;
744 Pixmap sourcePixmap
= (Pixmap
) NULL
;
745 double scaleX
, scaleY
;
746 GetUserScale(& scaleX
, & scaleY
);
748 /* TODO: use the mask origin when drawing transparently */
749 if (xsrcMask
== -1 && ysrcMask
== -1)
751 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
754 // Sorry, can't scale masks just yet
755 if (!useMask
&& (scaleX
!= 1.0 || scaleY
!= 1.0) && sourceDC
->IsKindOf(CLASSINFO(wxMemoryDC
)))
757 wxMemoryDC
* memDC
= (wxMemoryDC
*) sourceDC
;
758 wxBitmap
& bitmap
= memDC
->GetBitmap();
760 wxASSERT_MSG( (bitmap
.Ok()), "Bad source bitmap in wxWindowDC::Blit");
762 wxImage
image(bitmap
);
765 sourcePixmap
= (Pixmap
) bitmap
.GetPixmap();
769 int scaledW
= (int) (bitmap
.GetWidth() * scaleX
);
770 int scaledH
= (int) (bitmap
.GetHeight() * scaleY
);
772 image
= image
.Scale(scaledW
, scaledH
);
773 scaledBitmap
= new wxBitmap(image
.ConvertToBitmap());
774 sourcePixmap
= (Pixmap
) scaledBitmap
->GetPixmap();
778 sourcePixmap
= (Pixmap
) sourceDC
->m_pixmap
;
780 if (m_pixmap
&& sourcePixmap
)
783 int orig
= m_logicalFunction
;
785 SetLogicalFunction (rop
);
787 if (m_display
!= sourceDC
->m_display
)
789 XImage
*cache
= NULL
;
792 if (m_window
&& m_window
->GetBackingPixmap())
793 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
,
794 (Pixmap
) sourcePixmap
, (Pixmap
) m_window
->GetBackingPixmap(),
796 source
->LogicalToDeviceX (xsrc
),
797 source
->LogicalToDeviceY (ysrc
),
798 source
->LogicalToDeviceXRel(width
),
799 source
->LogicalToDeviceYRel(height
),
800 XLOG2DEV_2 (xdest
), YLOG2DEV_2 (ydest
),
804 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
806 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
807 wxBitmap
& sel
= memDC
->GetBitmap();
808 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
810 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
811 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
815 XCopyRemote((Display
*) sourceDC
->m_display
, (Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
816 source
->LogicalToDeviceX (xsrc
),
817 source
->LogicalToDeviceY (ysrc
),
818 source
->LogicalToDeviceXRel(width
),
819 source
->LogicalToDeviceYRel(height
),
820 XLOG2DEV (xdest
), YLOG2DEV (ydest
),
825 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
826 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
831 if ( useMask
&& source
->IsKindOf(CLASSINFO(wxMemoryDC
)) )
833 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
834 wxBitmap
& sel
= memDC
->GetBitmap();
835 if ( sel
.Ok() && sel
.GetMask() && sel
.GetMask()->GetPixmap() )
837 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) sel
.GetMask()->GetPixmap());
838 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, XLOG2DEV (xdest
), YLOG2DEV (ydest
));
842 // Check if we're copying from a mono bitmap
843 if (source
->IsKindOf(CLASSINFO(wxMemoryDC
)) &&
844 ((wxMemoryDC
*)source
)->GetBitmap().Ok() && (((wxMemoryDC
*)source
)->GetBitmap().GetDepth () == 1))
846 XCopyPlane ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
847 source
->LogicalToDeviceX (xsrc
),
848 source
->LogicalToDeviceY (ysrc
),
849 source
->LogicalToDeviceXRel(width
),
850 source
->LogicalToDeviceYRel(height
),
851 XLOG2DEV (xdest
), YLOG2DEV (ydest
), 1);
855 XCopyArea ((Display
*) m_display
, (Pixmap
) sourcePixmap
, (Pixmap
) m_pixmap
, (GC
) m_gc
,
856 source
->LogicalToDeviceX (xsrc
),
857 source
->LogicalToDeviceY (ysrc
),
858 source
->LogicalToDeviceXRel(width
),
859 source
->LogicalToDeviceYRel(height
),
860 XLOG2DEV (xdest
), YLOG2DEV (ydest
));
865 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
866 XSetClipOrigin ((Display
*) m_display
, (GC
) m_gc
, 0, 0);
869 } /* Remote/local (Display*) m_display */
870 CalcBoundingBox (xdest
, ydest
);
871 CalcBoundingBox (xdest
+ width
, ydest
+ height
);
873 SetLogicalFunction(orig
);
875 if (scaledBitmap
) delete scaledBitmap
;
879 if (scaledBitmap
) delete scaledBitmap
;
884 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
886 wxCHECK_RET( Ok(), "invalid dc" );
888 // Since X draws from the baseline of the text, must add the text height
898 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
899 int direction
, descent
;
900 XCharStruct overall_return
;
903 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
904 &ascent
, &descent
, &overall_return
);
907 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
908 &ascent
, &descent
, &overall_return
);
910 cx
= overall_return
.width
;
911 cy
= ascent
+ descent
;
914 // First draw a rectangle representing the text background, if a text
915 // background is specified
916 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
918 wxColour oldPenColour
= m_currentColour
;
919 m_currentColour
= m_textBackgroundColour
;
920 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
921 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
922 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
923 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
925 // This separation of the big && test required for gcc2.7/HP UX 9.02
926 // or pixel value can be corrupted!
927 sameColour
= (sameColour
&&
928 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
930 if (!sameColour
|| !GetOptimization())
932 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
933 m_currentColour
= m_textBackgroundColour
;
935 // Set the GC to the required colour
938 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
942 m_textBackgroundColour
= oldPenColour
;
944 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
947 // Now set the text foreground and draw the text
948 if (m_textForegroundColour
.Ok ())
950 wxColour oldPenColour
= m_currentColour
;
951 m_currentColour
= m_textForegroundColour
;
952 bool sameColour
= (oldPenColour
.Ok () && m_currentColour
.Ok () &&
953 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
954 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
955 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
956 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
958 if (!sameColour
|| !GetOptimization())
961 if (!m_colour
) // Mono display
963 // Unless foreground is really white, draw it in black
964 unsigned char red
= m_textForegroundColour
.Red ();
965 unsigned char blue
= m_textForegroundColour
.Blue ();
966 unsigned char green
= m_textForegroundColour
.Green ();
967 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
968 && green
== (unsigned char) 255)
970 m_currentColour
= *wxWHITE
;
971 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
972 m_currentColour
.SetPixel(pixel
);
973 m_textForegroundColour
.SetPixel(pixel
);
977 m_currentColour
= *wxBLACK
;
978 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
979 m_currentColour
.SetPixel(pixel
);
980 m_textForegroundColour
.SetPixel(pixel
);
985 pixel
= m_textForegroundColour
.AllocColour((Display
*) m_display
);
986 m_currentColour
.SetPixel(pixel
);
989 // Set the GC to the required colour
992 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
996 m_textForegroundColour
= oldPenColour
;
999 // We need to add the ascent, not the whole height, since X draws at the
1000 // point above the descender.
1003 XDrawString16((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
,
1004 (XChar2b
*)(char*) (const char*) text
, slen
);
1007 XDrawString((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
) + ascent
, text
, slen
);
1010 GetTextExtent (text
, &w
, &h
);
1011 CalcBoundingBox (x
+ w
, y
+ h
);
1012 CalcBoundingBox (x
, y
);
1015 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1019 DrawText(text
, x
, y
);
1023 wxCHECK_RET( Ok(), "invalid dc" );
1025 // Since X draws from the baseline of the text, must add the text height
1031 slen
= strlen(text
);
1035 // Calculate text extent.
1036 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1037 int direction
, descent
;
1038 XCharStruct overall_return
;
1041 (void)XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*)(const char*) text
, slen
, &direction
,
1042 &ascent
, &descent
, &overall_return
);
1045 (void)XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) text
, slen
, &direction
,
1046 &ascent
, &descent
, &overall_return
);
1048 cx
= overall_return
.width
;
1049 cy
= ascent
+ descent
;
1052 wxBitmap
src(cx
, cy
);
1054 dc
.SelectObject(src
);
1055 dc
.SetFont(GetFont());
1056 dc
.SetBackground(*wxWHITE_BRUSH
);
1057 dc
.SetBrush(*wxBLACK_BRUSH
);
1059 dc
.DrawText(text
, 0, 0);
1060 dc
.SetFont(wxNullFont
);
1062 // Calculate the size of the rotated bounding box.
1063 double dx
= cos(angle
/ 180.0 * M_PI
);
1064 double dy
= sin(angle
/ 180.0 * M_PI
);
1065 double x4
= -cy
* dy
;
1066 double y4
= cy
* dx
;
1067 double x3
= cx
* dx
;
1068 double y3
= cx
* dy
;
1069 double x2
= x3
+ x4
;
1070 double y2
= y3
+ y4
;
1074 // Create image from the source bitmap after writing the text into it.
1077 int minx
= roundmin(0, roundmin(x4
, roundmin(x2
, x3
)));
1078 int miny
= roundmin(0, roundmin(y4
, roundmin(y2
, y3
)));
1079 int maxx
= roundmax(0, roundmax(x4
, roundmax(x2
, x3
)));
1080 int maxy
= roundmax(0, roundmax(y4
, roundmax(y2
, y3
)));
1082 // This rotates counterclockwise around the top left corner.
1083 for (int rx
= minx
; rx
< maxx
; rx
++)
1085 for (int ry
= miny
; ry
< maxy
; ry
++)
1087 // transform dest coords to source coords
1088 int sx
= (int) (rx
* dx
+ ry
* dy
+ 0.5);
1089 int sy
= (int) (ry
* dx
- rx
* dy
+ 0.5);
1090 if (sx
>= 0 && sx
< cx
&& sy
>= 0 && sy
< cy
)
1092 // draw black pixels, ignore white ones (i.e. transparent b/g)
1093 if (image
.GetRed(sx
, sy
) == 0)
1095 DrawPoint((wxCoord
) (x1
+ maxx
- rx
), (wxCoord
) (cy
+ y1
- ry
));
1100 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1107 // First draw a rectangle representing the text background, if a text
1108 // background is specified
1109 if (m_textBackgroundColour
.Ok () && (m_backgroundMode
!= wxTRANSPARENT
))
1111 wxColour oldPenColour
= m_currentColour
;
1112 m_currentColour
= m_textBackgroundColour
;
1113 bool sameColour
= (oldPenColour
.Ok () && m_textBackgroundColour
.Ok () &&
1114 (oldPenColour
.Red () == m_textBackgroundColour
.Red ()) &&
1115 (oldPenColour
.Blue () == m_textBackgroundColour
.Blue ()) &&
1116 (oldPenColour
.Green () == m_textBackgroundColour
.Green ()));
1118 // This separation of the big && test required for gcc2.7/HP UX 9.02
1119 // or pixel value can be corrupted!
1120 sameColour
= (sameColour
&&
1121 (oldPenColour
.GetPixel() == m_textBackgroundColour
.GetPixel()));
1123 if (!sameColour
|| !GetOptimization())
1125 int pixel
= m_textBackgroundColour
.AllocColour(m_display
);
1126 m_currentColour
= m_textBackgroundColour
;
1128 // Set the GC to the required colour
1131 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1135 m_textBackgroundColour
= oldPenColour
;
1137 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, XLOG2DEV (x
), YLOG2DEV (y
), cx
, cy
);
1142 // XXX use pixmap size
1143 GetTextExtent (text
, &w
, &h
);
1144 CalcBoundingBox (x
+ w
, y
+ h
);
1145 CalcBoundingBox (x
, y
);
1148 bool wxWindowDC::CanGetTextExtent() const
1153 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1154 wxCoord
*descent
, wxCoord
*externalLeading
,
1155 wxFont
*font
) const
1157 wxCHECK_RET( Ok(), "invalid dc" );
1159 wxFont
* theFont
= font
;
1161 theFont
= (wxFont
*)&m_font
; // const_cast
1165 // TODO: this should be an error log function
1166 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1168 if (width
) *width
= -1;
1169 if (height
) *height
= -1;
1173 WXFontStructPtr pFontStruct
= theFont
->GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1175 int direction
, ascent
, descent2
;
1176 XCharStruct overall
;
1181 slen
= str16len(string
);
1184 slen
= strlen(string
);
1188 XTextExtents16((XFontStruct
*) pFontStruct
, (XChar2b
*) (char*) (const char*) string
, slen
, &direction
,
1189 &ascent
, &descent2
, &overall
);
1192 XTextExtents((XFontStruct
*) pFontStruct
, (char*) (const char*) string
, slen
, &direction
,
1193 &ascent
, &descent2
, &overall
);
1195 if (width
) *width
= XDEV2LOGREL (overall
.width
);
1196 if (height
) *height
= YDEV2LOGREL (ascent
+ descent2
);
1198 *descent
= descent2
;
1199 if (externalLeading
)
1200 *externalLeading
= 0;
1203 wxCoord
wxWindowDC::GetCharWidth() const
1205 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1206 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1208 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
* m_logicalScaleY
, m_display
);
1210 int direction
, ascent
, descent
;
1211 XCharStruct overall
;
1212 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1213 &descent
, &overall
);
1214 return XDEV2LOGREL(overall
.width
);
1217 wxCoord
wxWindowDC::GetCharHeight() const
1219 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1220 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1222 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1224 int direction
, ascent
, descent
;
1225 XCharStruct overall
;
1226 XTextExtents ((XFontStruct
*) pFontStruct
, "x", 1, &direction
, &ascent
,
1227 &descent
, &overall
);
1228 // return XDEV2LOGREL(overall.ascent + overall.descent);
1229 return XDEV2LOGREL(ascent
+ descent
);
1232 void wxWindowDC::Clear()
1234 wxCHECK_RET( Ok(), "invalid dc" );
1239 m_window
->GetSize(&w
, &h
);
1243 if (this->IsKindOf(CLASSINFO(wxMemoryDC
)))
1245 wxMemoryDC
* memDC
= (wxMemoryDC
*) this;
1246 w
= memDC
->GetBitmap().GetWidth();
1247 h
= memDC
->GetBitmap().GetHeight();
1253 wxBrush saveBrush
= m_brush
;
1254 SetBrush (m_backgroundBrush
);
1256 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, 0, 0, w
, h
);
1258 m_brush
= saveBrush
;
1261 void wxWindowDC::Clear(const wxRect
& rect
)
1263 wxCHECK_RET( Ok(), "invalid dc" );
1265 int x
= rect
.x
; int y
= rect
.y
;
1266 int w
= rect
.width
; int h
= rect
.height
;
1268 wxBrush saveBrush
= m_brush
;
1269 SetBrush (m_backgroundBrush
);
1271 XFillRectangle ((Display
*) m_display
, (Pixmap
) m_pixmap
, (GC
) m_gc
, x
, y
, w
, h
);
1273 m_brush
= saveBrush
;
1276 void wxWindowDC::SetFont( const wxFont
&font
)
1278 wxCHECK_RET( Ok(), "invalid dc" );
1284 if ((m_oldFont
!= (WXFont
) 0) && ((wxCoord
) m_oldFont
!= -1))
1286 XSetFont ((Display
*) m_display
, (GC
) m_gc
, (Font
) m_oldFont
);
1291 WXFontStructPtr pFontStruct
= m_font
.GetFontStruct(m_userScaleY
*m_logicalScaleY
, m_display
);
1293 Font fontId
= ((XFontStruct
*)pFontStruct
)->fid
;
1294 XSetFont ((Display
*) m_display
, (GC
) m_gc
, fontId
);
1297 void wxWindowDC::SetPen( const wxPen
&pen
)
1299 wxCHECK_RET( Ok(), "invalid dc" );
1305 wxBitmap oldStipple
= m_currentStipple
;
1306 int oldStyle
= m_currentStyle
;
1307 int oldFill
= m_currentFill
;
1308 int old_pen_width
= m_currentPenWidth
;
1309 int old_pen_join
= m_currentPenJoin
;
1310 int old_pen_cap
= m_currentPenCap
;
1311 int old_pen_nb_dash
= m_currentPenDashCount
;
1312 wxX11Dash
*old_pen_dash
= m_currentPenDash
;
1314 wxColour oldPenColour
= m_currentColour
;
1315 m_currentColour
= m_pen
.GetColour ();
1316 m_currentStyle
= m_pen
.GetStyle ();
1317 m_currentFill
= m_pen
.GetStyle (); // TODO?
1318 m_currentPenWidth
= m_pen
.GetWidth ();
1319 m_currentPenJoin
= m_pen
.GetJoin ();
1320 m_currentPenCap
= m_pen
.GetCap ();
1321 m_currentPenDashCount
= m_pen
.GetDashCount();
1322 m_currentPenDash
= (wxX11Dash
*)m_pen
.GetDash();
1326 if (m_currentStyle
== wxSTIPPLE
)
1327 m_currentStipple
= * m_pen
.GetStipple ();
1330 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1331 oldFill
== m_currentFill
&&
1332 old_pen_join
== m_currentPenJoin
&&
1333 old_pen_cap
== m_currentPenCap
&&
1334 old_pen_nb_dash
== m_currentPenDashCount
&&
1335 old_pen_dash
== m_currentPenDash
&&
1336 old_pen_width
== m_currentPenWidth
);
1338 bool sameColour
= (oldPenColour
.Ok () &&
1339 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1340 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1341 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1342 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1344 if (!sameStyle
|| !GetOptimization())
1346 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1347 if (scaled_width
< 0)
1353 static const wxX11Dash dotted
[] = {2, 5};
1354 static const wxX11Dash short_dashed
[] = {4, 4};
1355 static const wxX11Dash long_dashed
[] = {4, 8};
1356 static const wxX11Dash dotted_dashed
[] = {6, 6, 2, 6};
1358 // We express dash pattern in pen width unit, so we are
1359 // independent of zoom factor and so on...
1361 const wxX11Dash
*req_dash
;
1363 switch (m_pen
.GetStyle ())
1366 req_nb_dash
= m_currentPenDashCount
;
1367 req_dash
= m_currentPenDash
;
1368 style
= LineOnOffDash
;
1373 style
= LineOnOffDash
;
1377 req_dash
= short_dashed
;
1378 style
= LineOnOffDash
;
1382 req_dash
= long_dashed
;
1383 style
= LineOnOffDash
;
1387 req_dash
= dotted_dashed
;
1388 style
= LineOnOffDash
;
1395 req_dash
= (wxX11Dash
*)NULL
;
1399 if (req_dash
&& req_nb_dash
)
1401 wxX11Dash
*real_req_dash
= new wxX11Dash
[req_nb_dash
];
1404 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1405 for (int i
= 0; i
< req_nb_dash
; i
++)
1406 real_req_dash
[i
] = req_dash
[i
] * factor
;
1407 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1408 delete[]real_req_dash
;
1412 // No Memory. We use non-scaled dash pattern...
1413 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1417 switch (m_pen
.GetCap ())
1419 case wxCAP_PROJECTING
:
1420 cap
= CapProjecting
;
1427 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1431 switch (m_pen
.GetJoin ())
1445 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1448 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1452 oldStipple
= wxNullBitmap
; // For later reset!!
1454 switch (m_currentFill
)
1456 case wxBDIAGONAL_HATCH
:
1457 if (bdiag
== (Pixmap
) 0)
1458 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1459 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1460 bdiag_bits
, bdiag_width
, bdiag_height
);
1463 case wxFDIAGONAL_HATCH
:
1464 if (fdiag
== (Pixmap
) 0)
1465 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1466 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1467 fdiag_bits
, fdiag_width
, fdiag_height
);
1471 if (cross
== (Pixmap
) 0)
1472 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1473 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1474 cross_bits
, cross_width
, cross_height
);
1477 case wxHORIZONTAL_HATCH
:
1478 if (horiz
== (Pixmap
) 0)
1479 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1480 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1481 horiz_bits
, horiz_width
, horiz_height
);
1484 case wxVERTICAL_HATCH
:
1485 if (verti
== (Pixmap
) 0)
1486 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1487 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1488 verti_bits
, verti_width
, verti_height
);
1491 case wxCROSSDIAG_HATCH
:
1493 if (cdiag
== (Pixmap
) 0)
1494 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1495 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1496 cdiag_bits
, cdiag_width
, cdiag_height
);
1500 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1502 else if (m_currentStipple
.Ok()
1503 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1505 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1508 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1512 if (m_currentFill
== wxSTIPPLE
)
1513 fill_style
= FillStippled
;
1514 else if (IS_HATCH (m_currentFill
))
1515 fill_style
= FillStippled
;
1517 fill_style
= FillSolid
;
1518 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1521 // must test m_logicalFunction, because it involves background!
1522 if (!sameColour
|| !GetOptimization()
1523 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1526 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1527 pixel
= m_backgroundPixel
;
1530 unsigned char red
= m_pen
.GetColour ().Red ();
1531 unsigned char blue
= m_pen
.GetColour ().Blue ();
1532 unsigned char green
= m_pen
.GetColour ().Green ();
1533 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1534 && green
== (unsigned char) 255)
1536 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1537 m_currentColour
= *wxWHITE
;
1538 m_pen
.GetColour().SetPixel(pixel
);
1539 m_currentColour
.SetPixel(pixel
);
1543 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1544 m_currentColour
= *wxBLACK
;
1545 m_pen
.GetColour().SetPixel(pixel
);
1550 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1551 m_currentColour
.SetPixel(pixel
);
1554 // Finally, set the GC to the required colour
1557 if (m_logicalFunction
== wxXOR
)
1560 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1561 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1565 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1570 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1575 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1577 wxCHECK_RET( Ok(), "invalid dc" );
1581 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1584 int oldFill
= m_currentFill
;
1585 wxBitmap oldStipple
= m_currentStipple
;
1587 m_autoSetting
|= 0x1;
1589 m_currentFill
= m_brush
.GetStyle ();
1590 if (m_currentFill
== wxSTIPPLE
)
1591 m_currentStipple
= * m_brush
.GetStipple ();
1593 wxColour
oldBrushColour(m_currentColour
);
1594 m_currentColour
= m_brush
.GetColour ();
1596 bool sameColour
= (oldBrushColour
.Ok () &&
1597 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1598 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1599 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1600 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1602 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1604 switch (brush
.GetStyle ())
1608 case wxBDIAGONAL_HATCH
:
1609 case wxCROSSDIAG_HATCH
:
1610 case wxFDIAGONAL_HATCH
:
1612 case wxHORIZONTAL_HATCH
:
1613 case wxVERTICAL_HATCH
:
1616 // Chris Breeze 23/07/97: use background mode to determine whether
1617 // fill style should be solid or transparent
1618 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1619 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1624 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1628 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1632 switch (m_currentFill
)
1634 case wxBDIAGONAL_HATCH
:
1635 if (bdiag
== (Pixmap
) 0)
1636 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1637 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1638 bdiag_bits
, bdiag_width
, bdiag_height
);
1641 case wxFDIAGONAL_HATCH
:
1642 if (fdiag
== (Pixmap
) 0)
1643 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1644 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1645 fdiag_bits
, fdiag_width
, fdiag_height
);
1649 if (cross
== (Pixmap
) 0)
1650 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1651 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1652 cross_bits
, cross_width
, cross_height
);
1655 case wxHORIZONTAL_HATCH
:
1656 if (horiz
== (Pixmap
) 0)
1657 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1658 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1659 horiz_bits
, horiz_width
, horiz_height
);
1662 case wxVERTICAL_HATCH
:
1663 if (verti
== (Pixmap
) 0)
1664 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1665 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1666 verti_bits
, verti_width
, verti_height
);
1669 case wxCROSSDIAG_HATCH
:
1671 if (cdiag
== (Pixmap
) 0)
1672 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1673 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1674 cdiag_bits
, cdiag_width
, cdiag_height
);
1678 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1680 // X can forget the stipple value when resizing a window (apparently)
1681 // so always set the stipple.
1682 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1684 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1687 // must test m_logicalFunction, because it involves background!
1688 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1693 // Policy - on a monochrome screen, all brushes are white,
1694 // except when they're REALLY black!!!
1695 unsigned char red
= m_brush
.GetColour ().Red ();
1696 unsigned char blue
= m_brush
.GetColour ().Blue ();
1697 unsigned char green
= m_brush
.GetColour ().Green ();
1699 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1700 && green
== (unsigned char) 0)
1702 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1703 m_currentColour
= *wxBLACK
;
1704 m_brush
.GetColour().SetPixel(pixel
);
1705 m_currentColour
.SetPixel(pixel
);
1709 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1710 m_currentColour
= *wxWHITE
;
1711 m_brush
.GetColour().SetPixel(pixel
);
1712 m_currentColour
.SetPixel(pixel
);
1715 // N.B. comment out the above line and uncomment the following lines
1716 // if you want non-white colours to be black on a monochrome display.
1718 if (red == (unsigned char )255 && blue == (unsigned char)255
1719 && green == (unsigned char)255)
1720 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1722 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1725 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1727 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1728 m_currentColour
.SetPixel(pixel
);
1732 // Finally, set the GC to the required colour
1733 if (m_logicalFunction
== wxXOR
)
1736 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1737 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1741 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1746 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1749 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1751 wxCHECK_RET( Ok(), "invalid dc" );
1753 m_backgroundBrush
= brush
;
1755 if (!m_backgroundBrush
.Ok())
1758 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1760 // New behaviour, 10/2/99: setting the background brush of a DC
1761 // doesn't affect the window background colour.
1763 // XSetWindowBackground doesn't work for non-Window pixmaps
1764 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1765 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1768 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1769 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1770 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1773 void wxWindowDC::SetLogicalFunction( int function
)
1775 wxCHECK_RET( Ok(), "invalid dc" );
1780 if (m_logicalFunction
== function
)
1786 x_function
= GXclear
;
1792 x_function
= GXinvert
;
1795 x_function
= GXorReverse
;
1798 x_function
= GXandReverse
;
1807 x_function
= GXandInverted
;
1810 x_function
= GXnoop
;
1816 x_function
= GXequiv
;
1819 x_function
= GXcopyInverted
;
1822 x_function
= GXorInverted
;
1825 x_function
= GXnand
;
1832 x_function
= GXcopy
;
1836 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1838 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1839 /* MATTHEW: [9] Need to redo pen simply */
1840 m_autoSetting
|= 0x2;
1842 m_logicalFunction
= function
;
1846 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1848 wxCHECK_RET( Ok(), "invalid dc" );
1850 if (m_textForegroundColour
== col
)
1853 m_textForegroundColour
= col
;
1857 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1859 wxCHECK_RET( Ok(), "invalid dc" );
1861 if (m_textBackgroundColour
== col
)
1864 m_textBackgroundColour
= col
;
1865 if (!m_textBackgroundColour
.Ok())
1869 void wxWindowDC::SetBackgroundMode( int mode
)
1871 m_backgroundMode
= mode
;
1874 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1879 /* Use GetXColormap */
1880 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1881 (Colormap
) palette
.GetXColormap());
1883 /* Use wxGetMainColormap */
1884 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1885 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1890 void wxWindowDC::SetDCClipping()
1892 // m_userRegion is the region set by calling SetClippingRegion
1894 if (m_currentRegion
)
1895 XDestroyRegion ((Region
) m_currentRegion
);
1897 // We need to take into account
1898 // clipping imposed on a window by a repaint.
1899 // We'll combine it with the user region. But for now,
1900 // just use the currently-defined user clipping region.
1901 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
1902 m_currentRegion
= (WXRegion
) XCreateRegion ();
1904 m_currentRegion
= (WXRegion
) NULL
;
1906 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
1907 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetX11Region(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
1908 else if (m_userRegion
)
1909 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
1910 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
1911 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetX11Region(), (Region
) m_window
->GetUpdateRegion().GetX11Region(),
1912 (Region
) m_currentRegion
);
1914 if (m_currentRegion
)
1916 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
1920 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1925 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1927 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1930 XDestroyRegion ((Region
) m_userRegion
);
1931 m_userRegion
= (WXRegion
) XCreateRegion ();
1935 r
.width
= XLOG2DEVREL(width
);
1936 r
.height
= YLOG2DEVREL(height
);
1937 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
1942 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
1944 wxRect box
= region
.GetBox();
1946 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
1949 XDestroyRegion ((Region
) m_userRegion
);
1950 m_userRegion
= (WXRegion
) XCreateRegion ();
1952 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetX11Region(), (Region
) m_userRegion
);
1958 void wxWindowDC::DestroyClippingRegion()
1960 wxDC::DestroyClippingRegion();
1963 XDestroyRegion ((Region
) m_userRegion
);
1964 m_userRegion
= NULL
;
1969 gc_val
.clip_mask
= None
;
1972 // Resolution in pixels per logical inch
1973 wxSize
wxWindowDC::GetPPI() const
1975 return wxSize(100, 100);
1978 int wxWindowDC::GetDepth() const
1987 // ----------------------------------------------------------------------------
1989 // ----------------------------------------------------------------------------
1991 wxPaintDC::wxPaintDC(wxWindow
* win
)
1994 // TODO clone GTK logic here
1997 wxPaintDC::~wxPaintDC()
2001 // ----------------------------------------------------------------------------
2002 // private functions
2003 // ----------------------------------------------------------------------------
2006 Used when copying between drawables on different (Display*) m_displays. Not
2007 very fast, but better than giving up.
2010 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2011 Drawable src
, Drawable dest
,
2014 unsigned int w
, unsigned int h
,
2015 int destx
, int desty
,
2016 bool more
, XImage
**cache
)
2018 XImage
*image
, *destimage
;
2019 Colormap destcm
, srccm
;
2020 static const int CACHE_SIZE
= 256;
2023 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2024 int k
, cache_pos
, all_cache
;
2026 if (!cache
|| !*cache
)
2027 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2031 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2033 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2034 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2039 for (i
= 0; i
< w
; i
++)
2040 for (j
= 0; j
< h
; j
++) {
2041 unsigned long pixel
;
2044 pixel
= XGetPixel(image
, i
, j
);
2045 for (k
= cache_pos
; k
--; )
2046 if (cachesrc
[k
] == pixel
) {
2047 pixel
= cachedest
[k
];
2051 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2052 if (cachesrc
[k
] == pixel
) {
2053 pixel
= cachedest
[k
];
2057 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2058 XQueryColor(src_display
, srccm
, &xcol
);
2059 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2061 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2063 if (++cache_pos
>= CACHE_SIZE
) {
2069 XPutPixel(destimage
, i
, j
, pixel
);
2072 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2073 XDestroyImage(destimage
);
2078 XDestroyImage(image
);
2083 /* Helper function for 16-bit fonts */
2084 static int str16len(const char *s
)
2088 while (s
[0] && s
[1]) {