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
= (wxMOTIFDash
*) 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
= (wxMOTIFDash
*) 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 wxMOTIFDash
*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
= (wxMOTIFDash
*)m_pen
.GetDash();
1324 if (m_currentStyle
== wxSTIPPLE
)
1325 m_currentStipple
= * m_pen
.GetStipple ();
1327 bool sameStyle
= (oldStyle
== m_currentStyle
&&
1328 oldFill
== m_currentFill
&&
1329 old_pen_join
== m_currentPenJoin
&&
1330 old_pen_cap
== m_currentPenCap
&&
1331 old_pen_nb_dash
== m_currentPenDashCount
&&
1332 old_pen_dash
== m_currentPenDash
&&
1333 old_pen_width
== m_currentPenWidth
);
1335 bool sameColour
= (oldPenColour
.Ok () &&
1336 (oldPenColour
.Red () == m_currentColour
.Red ()) &&
1337 (oldPenColour
.Blue () == m_currentColour
.Blue ()) &&
1338 (oldPenColour
.Green () == m_currentColour
.Green ()) &&
1339 (oldPenColour
.GetPixel() == m_currentColour
.GetPixel()));
1341 if (!sameStyle
|| !GetOptimization())
1343 int scaled_width
= (int) XLOG2DEVREL (m_pen
.GetWidth ());
1344 if (scaled_width
< 0)
1350 static const wxMOTIFDash dotted
[] = {2, 5};
1351 static const wxMOTIFDash short_dashed
[] = {4, 4};
1352 static const wxMOTIFDash long_dashed
[] = {4, 8};
1353 static const wxMOTIFDash dotted_dashed
[] = {6, 6, 2, 6};
1355 // We express dash pattern in pen width unit, so we are
1356 // independent of zoom factor and so on...
1358 const wxMOTIFDash
*req_dash
;
1360 switch (m_pen
.GetStyle ())
1363 req_nb_dash
= m_currentPenDashCount
;
1364 req_dash
= m_currentPenDash
;
1365 style
= LineOnOffDash
;
1370 style
= LineOnOffDash
;
1374 req_dash
= short_dashed
;
1375 style
= LineOnOffDash
;
1379 req_dash
= long_dashed
;
1380 style
= LineOnOffDash
;
1384 req_dash
= dotted_dashed
;
1385 style
= LineOnOffDash
;
1392 req_dash
= (wxMOTIFDash
*)NULL
;
1396 if (req_dash
&& req_nb_dash
)
1398 wxMOTIFDash
*real_req_dash
= new wxMOTIFDash
[req_nb_dash
];
1401 int factor
= scaled_width
== 0 ? 1 : scaled_width
;
1402 for (int i
= 0; i
< req_nb_dash
; i
++)
1403 real_req_dash
[i
] = req_dash
[i
] * factor
;
1404 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, real_req_dash
, req_nb_dash
);
1405 delete[]real_req_dash
;
1409 // No Memory. We use non-scaled dash pattern...
1410 XSetDashes ((Display
*) m_display
, (GC
) m_gc
, 0, req_dash
, req_nb_dash
);
1414 switch (m_pen
.GetCap ())
1416 case wxCAP_PROJECTING
:
1417 cap
= CapProjecting
;
1424 cap
= (scaled_width
<= 1) ? CapNotLast
: CapRound
;
1428 switch (m_pen
.GetJoin ())
1442 XSetLineAttributes ((Display
*) m_display
, (GC
) m_gc
, scaled_width
, style
, cap
, join
);
1445 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1449 oldStipple
= wxNullBitmap
; // For later reset!!
1451 switch (m_currentFill
)
1453 case wxBDIAGONAL_HATCH
:
1454 if (bdiag
== (Pixmap
) 0)
1455 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1456 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1457 bdiag_bits
, bdiag_width
, bdiag_height
);
1460 case wxFDIAGONAL_HATCH
:
1461 if (fdiag
== (Pixmap
) 0)
1462 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1463 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1464 fdiag_bits
, fdiag_width
, fdiag_height
);
1468 if (cross
== (Pixmap
) 0)
1469 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1470 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1471 cross_bits
, cross_width
, cross_height
);
1474 case wxHORIZONTAL_HATCH
:
1475 if (horiz
== (Pixmap
) 0)
1476 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1477 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1478 horiz_bits
, horiz_width
, horiz_height
);
1481 case wxVERTICAL_HATCH
:
1482 if (verti
== (Pixmap
) 0)
1483 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1484 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1485 verti_bits
, verti_width
, verti_height
);
1488 case wxCROSSDIAG_HATCH
:
1490 if (cdiag
== (Pixmap
) 0)
1491 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1492 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1493 cdiag_bits
, cdiag_width
, cdiag_height
);
1497 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1499 else if (m_currentStipple
.Ok()
1500 && ((m_currentStipple
!= oldStipple
) || !GetOptimization()))
1502 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1505 if ((m_currentFill
!= oldFill
) || !GetOptimization())
1509 if (m_currentFill
== wxSTIPPLE
)
1510 fill_style
= FillStippled
;
1511 else if (IS_HATCH (m_currentFill
))
1512 fill_style
= FillStippled
;
1514 fill_style
= FillSolid
;
1515 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, fill_style
);
1518 // must test m_logicalFunction, because it involves background!
1519 if (!sameColour
|| !GetOptimization()
1520 || ((m_logicalFunction
== wxXOR
) || (m_autoSetting
& 0x2)))
1523 if (m_pen
.GetStyle () == wxTRANSPARENT
)
1524 pixel
= m_backgroundPixel
;
1527 unsigned char red
= m_pen
.GetColour ().Red ();
1528 unsigned char blue
= m_pen
.GetColour ().Blue ();
1529 unsigned char green
= m_pen
.GetColour ().Green ();
1530 if (red
== (unsigned char) 255 && blue
== (unsigned char) 255
1531 && green
== (unsigned char) 255)
1533 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1534 m_currentColour
= *wxWHITE
;
1535 m_pen
.GetColour().SetPixel(pixel
);
1536 m_currentColour
.SetPixel(pixel
);
1540 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1541 m_currentColour
= *wxBLACK
;
1542 m_pen
.GetColour().SetPixel(pixel
);
1547 pixel
= m_pen
.GetColour ().AllocColour(m_display
);
1548 m_currentColour
.SetPixel(pixel
);
1551 // Finally, set the GC to the required colour
1554 if (m_logicalFunction
== wxXOR
)
1557 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1558 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1562 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1567 m_pen
.GetColour().SetPixel(oldPenColour
.GetPixel());
1572 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1574 wxCHECK_RET( Ok(), "invalid dc" );
1578 if (!m_brush
.Ok() || m_brush
.GetStyle () == wxTRANSPARENT
)
1581 int oldFill
= m_currentFill
;
1582 wxBitmap oldStipple
= m_currentStipple
;
1584 m_autoSetting
|= 0x1;
1586 m_currentFill
= m_brush
.GetStyle ();
1587 if (m_currentFill
== wxSTIPPLE
)
1588 m_currentStipple
= * m_brush
.GetStipple ();
1590 wxColour
oldBrushColour(m_currentColour
);
1591 m_currentColour
= m_brush
.GetColour ();
1593 bool sameColour
= (oldBrushColour
.Ok () &&
1594 (oldBrushColour
.Red () == m_currentColour
.Red ()) &&
1595 (oldBrushColour
.Blue () == m_currentColour
.Blue ()) &&
1596 (oldBrushColour
.Green () == m_currentColour
.Green ()) &&
1597 (oldBrushColour
.GetPixel() == m_currentColour
.GetPixel()));
1599 if ((oldFill
!= m_brush
.GetStyle ()) || !GetOptimization())
1601 switch (brush
.GetStyle ())
1605 case wxBDIAGONAL_HATCH
:
1606 case wxCROSSDIAG_HATCH
:
1607 case wxFDIAGONAL_HATCH
:
1609 case wxHORIZONTAL_HATCH
:
1610 case wxVERTICAL_HATCH
:
1613 // Chris Breeze 23/07/97: use background mode to determine whether
1614 // fill style should be solid or transparent
1615 int style
= (m_backgroundMode
== wxSOLID
? FillOpaqueStippled
: FillStippled
);
1616 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, style
);
1621 XSetFillStyle ((Display
*) m_display
, (GC
) m_gc
, FillSolid
);
1625 if (IS_HATCH(m_currentFill
) && ((m_currentFill
!= oldFill
) || !GetOptimization()))
1629 switch (m_currentFill
)
1631 case wxBDIAGONAL_HATCH
:
1632 if (bdiag
== (Pixmap
) 0)
1633 bdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1634 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1635 bdiag_bits
, bdiag_width
, bdiag_height
);
1638 case wxFDIAGONAL_HATCH
:
1639 if (fdiag
== (Pixmap
) 0)
1640 fdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1641 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1642 fdiag_bits
, fdiag_width
, fdiag_height
);
1646 if (cross
== (Pixmap
) 0)
1647 cross
= XCreateBitmapFromData ((Display
*) m_display
,
1648 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1649 cross_bits
, cross_width
, cross_height
);
1652 case wxHORIZONTAL_HATCH
:
1653 if (horiz
== (Pixmap
) 0)
1654 horiz
= XCreateBitmapFromData ((Display
*) m_display
,
1655 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1656 horiz_bits
, horiz_width
, horiz_height
);
1659 case wxVERTICAL_HATCH
:
1660 if (verti
== (Pixmap
) 0)
1661 verti
= XCreateBitmapFromData ((Display
*) m_display
,
1662 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1663 verti_bits
, verti_width
, verti_height
);
1666 case wxCROSSDIAG_HATCH
:
1668 if (cdiag
== (Pixmap
) 0)
1669 cdiag
= XCreateBitmapFromData ((Display
*) m_display
,
1670 RootWindow ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
)),
1671 cdiag_bits
, cdiag_width
, cdiag_height
);
1675 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, myStipple
);
1677 // X can forget the stipple value when resizing a window (apparently)
1678 // so always set the stipple.
1679 else if (m_currentStipple
.Ok()) // && m_currentStipple != oldStipple)
1681 XSetStipple ((Display
*) m_display
, (GC
) m_gc
, (Pixmap
) m_currentStipple
.GetPixmap());
1684 // must test m_logicalFunction, because it involves background!
1685 if (!sameColour
|| !GetOptimization() || m_logicalFunction
== wxXOR
)
1690 // Policy - on a monochrome screen, all brushes are white,
1691 // except when they're REALLY black!!!
1692 unsigned char red
= m_brush
.GetColour ().Red ();
1693 unsigned char blue
= m_brush
.GetColour ().Blue ();
1694 unsigned char green
= m_brush
.GetColour ().Green ();
1696 if (red
== (unsigned char) 0 && blue
== (unsigned char) 0
1697 && green
== (unsigned char) 0)
1699 pixel
= (int) BlackPixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1700 m_currentColour
= *wxBLACK
;
1701 m_brush
.GetColour().SetPixel(pixel
);
1702 m_currentColour
.SetPixel(pixel
);
1706 pixel
= (int) WhitePixel ((Display
*) m_display
, DefaultScreen ((Display
*) m_display
));
1707 m_currentColour
= *wxWHITE
;
1708 m_brush
.GetColour().SetPixel(pixel
);
1709 m_currentColour
.SetPixel(pixel
);
1712 // N.B. comment out the above line and uncomment the following lines
1713 // if you want non-white colours to be black on a monochrome display.
1715 if (red == (unsigned char )255 && blue == (unsigned char)255
1716 && green == (unsigned char)255)
1717 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1719 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1722 else if (m_brush
.GetStyle () != wxTRANSPARENT
)
1724 pixel
= m_brush
.GetColour().AllocColour(m_display
);
1725 m_currentColour
.SetPixel(pixel
);
1729 // Finally, set the GC to the required colour
1730 if (m_logicalFunction
== wxXOR
)
1733 XGetGCValues ((Display
*) m_display
, (GC
) m_gc
, GCBackground
, &values
);
1734 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
^ values
.background
);
1738 XSetForeground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1743 m_brush
.GetColour().SetPixel(oldBrushColour
.GetPixel());
1746 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1748 wxCHECK_RET( Ok(), "invalid dc" );
1750 m_backgroundBrush
= brush
;
1752 if (!m_backgroundBrush
.Ok())
1755 int pixel
= m_backgroundBrush
.GetColour().AllocColour(m_display
);
1757 // New behaviour, 10/2/99: setting the background brush of a DC
1758 // doesn't affect the window background colour.
1760 // XSetWindowBackground doesn't work for non-Window pixmaps
1761 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1762 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1765 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1766 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1767 XSetBackground ((Display
*) m_display
, (GC
) m_gc
, pixel
);
1770 void wxWindowDC::SetLogicalFunction( int function
)
1772 wxCHECK_RET( Ok(), "invalid dc" );
1777 if (m_logicalFunction
== function
)
1783 x_function
= GXclear
;
1789 x_function
= GXinvert
;
1792 x_function
= GXorReverse
;
1795 x_function
= GXandReverse
;
1804 x_function
= GXandInverted
;
1807 x_function
= GXnoop
;
1813 x_function
= GXequiv
;
1816 x_function
= GXcopyInverted
;
1819 x_function
= GXorInverted
;
1822 x_function
= GXnand
;
1829 x_function
= GXcopy
;
1833 XSetFunction((Display
*) m_display
, (GC
) m_gc
, x_function
);
1835 if ((m_logicalFunction
== wxXOR
) != (function
== wxXOR
))
1836 /* MATTHEW: [9] Need to redo pen simply */
1837 m_autoSetting
|= 0x2;
1839 m_logicalFunction
= function
;
1843 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1845 wxCHECK_RET( Ok(), "invalid dc" );
1847 if (m_textForegroundColour
== col
)
1850 m_textForegroundColour
= col
;
1854 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1856 wxCHECK_RET( Ok(), "invalid dc" );
1858 if (m_textBackgroundColour
== col
)
1861 m_textBackgroundColour
= col
;
1862 if (!m_textBackgroundColour
.Ok())
1866 void wxWindowDC::SetBackgroundMode( int mode
)
1868 m_backgroundMode
= mode
;
1871 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1876 /* Use GetXColormap */
1877 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1878 (Colormap
) palette
.GetXColormap());
1880 /* Use wxGetMainColormap */
1881 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1882 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1887 void wxWindowDC::SetDCClipping()
1889 // m_userRegion is the region set by calling SetClippingRegion
1891 if (m_currentRegion
)
1892 XDestroyRegion ((Region
) m_currentRegion
);
1894 // We need to take into account
1895 // clipping imposed on a window by a repaint.
1896 // We'll combine it with the user region. But for now,
1897 // just use the currently-defined user clipping region.
1898 if (m_userRegion
|| (m_window
&& m_window
->GetUpdateRegion().Ok()) )
1899 m_currentRegion
= (WXRegion
) XCreateRegion ();
1901 m_currentRegion
= (WXRegion
) NULL
;
1903 if ((m_window
&& m_window
->GetUpdateRegion().Ok()) && m_userRegion
)
1904 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetX11Region(), (Region
) m_userRegion
, (Region
) m_currentRegion
);
1905 else if (m_userRegion
)
1906 XIntersectRegion ((Region
) m_userRegion
, (Region
) m_userRegion
, (Region
) m_currentRegion
);
1907 else if (m_window
&& m_window
->GetUpdateRegion().Ok())
1908 XIntersectRegion ((Region
) m_window
->GetUpdateRegion().GetX11Region(), (Region
) m_window
->GetUpdateRegion().GetX11Region(),
1909 (Region
) m_currentRegion
);
1911 if (m_currentRegion
)
1913 XSetRegion ((Display
*) m_display
, (GC
) m_gc
, (Region
) m_currentRegion
);
1917 XSetClipMask ((Display
*) m_display
, (GC
) m_gc
, None
);
1922 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1924 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1927 XDestroyRegion ((Region
) m_userRegion
);
1928 m_userRegion
= (WXRegion
) XCreateRegion ();
1932 r
.width
= XLOG2DEVREL(width
);
1933 r
.height
= YLOG2DEVREL(height
);
1934 XUnionRectWithRegion (&r
, (Region
) m_userRegion
, (Region
) m_userRegion
);
1939 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
1941 wxRect box
= region
.GetBox();
1943 wxDC::DoSetClippingRegion( box
.x
, box
.y
, box
.width
, box
.height
);
1946 XDestroyRegion ((Region
) m_userRegion
);
1947 m_userRegion
= (WXRegion
) XCreateRegion ();
1949 XUnionRegion((Region
) m_userRegion
, (Region
) region
.GetX11Region(), (Region
) m_userRegion
);
1955 void wxWindowDC::DestroyClippingRegion()
1957 wxDC::DestroyClippingRegion();
1960 XDestroyRegion ((Region
) m_userRegion
);
1961 m_userRegion
= NULL
;
1966 gc_val
.clip_mask
= None
;
1969 // Resolution in pixels per logical inch
1970 wxSize
wxWindowDC::GetPPI() const
1972 return wxSize(100, 100);
1975 int wxWindowDC::GetDepth() const
1984 // ----------------------------------------------------------------------------
1986 // ----------------------------------------------------------------------------
1988 wxPaintDC::wxPaintDC(wxWindow
* win
)
1991 // TODO clone GTK logic here
1994 wxPaintDC::~wxPaintDC()
1998 // ----------------------------------------------------------------------------
1999 // private functions
2000 // ----------------------------------------------------------------------------
2003 Used when copying between drawables on different (Display*) m_displays. Not
2004 very fast, but better than giving up.
2007 static void XCopyRemote(Display
*src_display
, Display
*dest_display
,
2008 Drawable src
, Drawable dest
,
2011 unsigned int w
, unsigned int h
,
2012 int destx
, int desty
,
2013 bool more
, XImage
**cache
)
2015 XImage
*image
, *destimage
;
2016 Colormap destcm
, srccm
;
2017 static const int CACHE_SIZE
= 256;
2020 unsigned long cachesrc
[CACHE_SIZE
], cachedest
[CACHE_SIZE
];
2021 int k
, cache_pos
, all_cache
;
2023 if (!cache
|| !*cache
)
2024 image
= XGetImage(src_display
, src
, srcx
, srcy
, w
, h
, AllPlanes
, ZPixmap
);
2028 destimage
= XGetImage(dest_display
, dest
, destx
, desty
, w
, h
, AllPlanes
, ZPixmap
);
2030 srccm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) src_display
);
2031 destcm
= (Colormap
) wxTheApp
->GetMainColormap((WXDisplay
*) dest_display
);
2036 for (i
= 0; i
< w
; i
++)
2037 for (j
= 0; j
< h
; j
++) {
2038 unsigned long pixel
;
2041 pixel
= XGetPixel(image
, i
, j
);
2042 for (k
= cache_pos
; k
--; )
2043 if (cachesrc
[k
] == pixel
) {
2044 pixel
= cachedest
[k
];
2048 for (k
= CACHE_SIZE
; k
-- > cache_pos
; )
2049 if (cachesrc
[k
] == pixel
) {
2050 pixel
= cachedest
[k
];
2054 cachesrc
[cache_pos
] = xcol
.pixel
= pixel
;
2055 XQueryColor(src_display
, srccm
, &xcol
);
2056 if (!XAllocColor(dest_display
, destcm
, &xcol
))
2058 cachedest
[cache_pos
] = pixel
= xcol
.pixel
;
2060 if (++cache_pos
>= CACHE_SIZE
) {
2066 XPutPixel(destimage
, i
, j
, pixel
);
2069 XPutImage(dest_display
, dest
, destgc
, destimage
, 0, 0, destx
, desty
, w
, h
);
2070 XDestroyImage(destimage
);
2075 XDestroyImage(image
);
2080 /* Helper function for 16-bit fonts */
2081 static int str16len(const char *s
)
2085 while (s
[0] && s
[1]) {