1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: Julian Smart, Robert Roebling
8 // Copyright: (c) Julian Smart, Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dcclient.h"
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
18 #include "wx/window.h"
22 #include "wx/x11/private.h"
26 //-----------------------------------------------------------------------------
28 //-----------------------------------------------------------------------------
30 #define USE_PAINT_REGION 1
32 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
44 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
45 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
47 static Pixmap hatches
[num_hatches
];
48 static Pixmap
*hatch_bitmap
= (Pixmap
*) NULL
;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
54 const double RAD2DEG
= 180.0 / M_PI
;
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
61 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
63 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
65 //-----------------------------------------------------------------------------
66 // Implement Pool of Graphic contexts. Creating them takes too much time.
67 //-----------------------------------------------------------------------------
69 #define GC_POOL_SIZE 200
95 static wxGC wxGCPool
[GC_POOL_SIZE
];
97 static void wxInitGCPool()
99 memset( wxGCPool
, 0, GC_POOL_SIZE
*sizeof(wxGC
) );
102 static void wxCleanUpGCPool()
104 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
106 if (wxGCPool
[i
].m_gc
)
107 XFreeGC( wxGlobalDisplay(), wxGCPool
[i
].m_gc
);
111 static GC
wxGetPoolGC( Window window
, wxPoolGCType type
)
113 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
115 if (!wxGCPool
[i
].m_gc
)
117 wxGCPool
[i
].m_gc
= XCreateGC( wxGlobalDisplay(), window
, 0, NULL
);
118 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool
[i
].m_gc
, FALSE
);
119 wxGCPool
[i
].m_type
= type
;
120 wxGCPool
[i
].m_used
= FALSE
;
122 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
124 wxGCPool
[i
].m_used
= TRUE
;
125 return wxGCPool
[i
].m_gc
;
129 wxFAIL_MSG( wxT("No GC available") );
134 static void wxFreePoolGC( GC gc
)
136 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
138 if (wxGCPool
[i
].m_gc
== gc
)
140 wxGCPool
[i
].m_used
= FALSE
;
145 wxFAIL_MSG( wxT("Wrong GC") );
148 // ----------------------------------------------------------------------------
150 // ----------------------------------------------------------------------------
152 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
154 wxWindowDC::wxWindowDC()
156 m_display
= (WXDisplay
*) NULL
;
157 m_penGC
= (WXGC
*) NULL
;
158 m_brushGC
= (WXGC
*) NULL
;
159 m_textGC
= (WXGC
*) NULL
;
160 m_bgGC
= (WXGC
*) NULL
;
161 m_cmap
= (WXColormap
*) NULL
;
163 m_isScreenDC
= FALSE
;
164 m_owner
= (wxWindow
*)NULL
;
167 wxWindowDC::wxWindowDC( wxWindow
*window
)
169 wxASSERT_MSG( window
, wxT("DC needs a window") );
171 m_display
= (WXDisplay
*) NULL
;
172 m_penGC
= (WXGC
*) NULL
;
173 m_brushGC
= (WXGC
*) NULL
;
174 m_textGC
= (WXGC
*) NULL
;
175 m_bgGC
= (WXGC
*) NULL
;
176 m_cmap
= (WXColormap
*) NULL
;
177 m_owner
= (wxWindow
*)NULL
;
179 m_isScreenDC
= FALSE
;
180 m_font
= window
->GetFont();
182 m_window
= (WXWindow
*) window
->GetMainWindow();
187 // don't report problems
193 m_display
= (WXDisplay
*) wxGlobalDisplay();
195 int screen
= DefaultScreen( (Display
*) m_display
);
196 m_cmap
= (WXColormap
) DefaultColormap( (Display
*) m_display
, screen
);
200 /* this must be done after SetUpDC, bacause SetUpDC calls the
201 repective SetBrush, SetPen, SetBackground etc functions
202 to set up the DC. SetBackground call m_owner->SetBackground
203 and this might not be desired as the standard dc background
204 is white whereas a window might assume gray to be the
205 standard (as e.g. wxStatusBar) */
210 wxWindowDC::~wxWindowDC()
215 void wxWindowDC::SetUpDC()
219 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
223 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_SCREEN
);
224 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_SCREEN
);
225 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_SCREEN
);
226 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_SCREEN
);
230 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
232 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_MONO
);
233 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_MONO
);
234 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_MONO
);
235 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_MONO
);
240 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_COLOUR
);
241 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_COLOUR
);
242 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_COLOUR
);
243 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_COLOUR
);
246 /* background colour */
247 m_backgroundBrush
= *wxWHITE_BRUSH
;
248 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
249 unsigned long bg_col
= m_backgroundBrush
.GetColour().GetPixel();
252 m_textForegroundColour
.CalcPixel( m_cmap
);
253 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
255 m_textBackgroundColour
.CalcPixel( m_cmap
);
256 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
258 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillSolid
);
261 m_pen
.GetColour().CalcPixel( m_cmap
);
262 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
263 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, bg_col
);
265 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, 0, LineSolid
, CapNotLast
, JoinRound
);
268 m_brush
.GetColour().CalcPixel( m_cmap
);
269 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
270 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, bg_col
);
272 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
275 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
276 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
278 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
281 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, GXcopy
);
282 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, GXcopy
);
283 XSetFunction( (Display
*) m_display
, (GC
)m_penGC
, GXcopy
);
286 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
287 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
288 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
289 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
293 int xscreen
= DefaultScreen( (Display
*) m_display
);
294 Window xroot
= RootWindow( (Display
*) m_display
, xscreen
);
296 hatch_bitmap
= hatches
;
297 hatch_bitmap
[0] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, bdiag_bits
, bdiag_width
, bdiag_height
);
298 hatch_bitmap
[1] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cdiag_bits
, cdiag_width
, cdiag_height
);
299 hatch_bitmap
[2] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, fdiag_bits
, fdiag_width
, fdiag_height
);
300 hatch_bitmap
[3] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cross_bits
, cross_width
, cross_height
);
301 hatch_bitmap
[4] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, horiz_bits
, horiz_width
, horiz_height
);
302 hatch_bitmap
[5] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, verti_bits
, verti_width
, verti_height
);
306 void wxWindowDC::DoGetSize( int* width
, int* height
) const
308 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
310 m_owner
->GetSize(width
, height
);
313 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
314 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
316 wxFAIL_MSG("not implemented");
319 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
321 // Generic (and therefore rather inefficient) method.
322 // Could be improved.
324 wxBitmap
bitmap(1, 1);
325 memdc
.SelectObject(bitmap
);
326 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
327 memdc
.SelectObject(wxNullBitmap
);
328 wxImage
image(bitmap
);
329 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
333 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
335 wxCHECK_RET( Ok(), wxT("invalid window dc") );
337 if (m_pen
.GetStyle() != wxTRANSPARENT
)
340 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
341 (GC
) m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
343 CalcBoundingBox(x1
, y1
);
344 CalcBoundingBox(x2
, y2
);
346 wxLogDebug("Drawing line at %d, %d -> %d, %d", XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
350 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
352 wxCHECK_RET( Ok(), wxT("invalid window dc") );
354 if (m_pen
.GetStyle() != wxTRANSPARENT
)
359 wxCoord xx
= XLOG2DEV(x
);
360 wxCoord yy
= YLOG2DEV(y
);
363 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
364 (GC
) m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
365 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
366 (GC
) m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
371 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
373 wxCHECK_RET( Ok(), wxT("invalid window dc") );
375 wxCoord xx1
= XLOG2DEV(x1
);
376 wxCoord yy1
= YLOG2DEV(y1
);
377 wxCoord xx2
= XLOG2DEV(x2
);
378 wxCoord yy2
= YLOG2DEV(y2
);
379 wxCoord xxc
= XLOG2DEV(xc
);
380 wxCoord yyc
= YLOG2DEV(yc
);
381 double dx
= xx1
- xxc
;
382 double dy
= yy1
- yyc
;
383 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
384 wxCoord r
= (wxCoord
)radius
;
385 double radius1
, radius2
;
387 if (xx1
== xx2
&& yy1
== yy2
)
395 radius1
= radius2
= 0.0;
399 radius1
= (xx1
- xxc
== 0) ?
400 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
401 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
402 radius2
= (xx2
- xxc
== 0) ?
403 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
404 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
406 wxCoord alpha1
= wxCoord(radius1
* 64.0);
407 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
408 while (alpha2
<= 0) alpha2
+= 360*64;
409 while (alpha1
> 360*64) alpha1
-= 360*64;
413 if (m_brush
.GetStyle() != wxTRANSPARENT
)
415 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
417 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
418 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
419 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
421 XFillArc( (Display
*) m_display
, (Window
) m_window
,
422 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
424 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
426 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
428 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
429 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
431 XFillArc( (Display
*) m_display
, (Window
) m_window
,
432 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
434 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
436 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
438 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
439 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
441 XFillArc( (Display
*) m_display
, (Window
) m_window
,
442 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
444 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
446 if (m_brush
.GetStyle() == wxSTIPPLE
)
448 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
449 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
450 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
452 XFillArc( (Display
*) m_display
, (Window
) m_window
,
453 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
455 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
459 XFillArc( (Display
*) m_display
, (Window
) m_window
,
460 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
464 if (m_pen
.GetStyle() != wxTRANSPARENT
)
466 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
467 (GC
) m_penGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
469 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
470 (GC
) m_penGC
, xx1
, yy1
, xxc
, yyc
);
472 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
473 (GC
) m_penGC
, xxc
, yyc
, xx2
, yy2
);
477 CalcBoundingBox (x1
, y1
);
478 CalcBoundingBox (x2
, y2
);
481 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
483 wxCHECK_RET( Ok(), wxT("invalid window dc") );
485 wxCoord xx
= XLOG2DEV(x
);
486 wxCoord yy
= YLOG2DEV(y
);
487 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
488 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
490 // CMB: handle -ve width and/or height
491 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
492 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
496 wxCoord start
= wxCoord(sa
* 64.0);
497 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
499 if (m_brush
.GetStyle() != wxTRANSPARENT
)
501 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
503 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
504 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
505 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
507 XFillArc( (Display
*) m_display
, (Window
) m_window
,
508 (GC
) m_textGC
, xx
, yy
, ww
, hh
, start
, end
);
510 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
512 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
514 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
515 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
517 XFillArc( (Display
*) m_display
, (Window
) m_window
,
518 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
520 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
522 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
524 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
525 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
527 XFillArc( (Display
*) m_display
, (Window
) m_window
,
528 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
530 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
532 if (m_brush
.GetStyle() == wxSTIPPLE
)
534 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
535 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
536 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
538 XFillArc( (Display
*) m_display
, (Window
) m_window
,
539 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
541 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
545 XFillArc( (Display
*) m_display
, (Window
) m_window
,
546 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
550 if (m_pen
.GetStyle() != wxTRANSPARENT
)
552 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
553 (GC
) m_penGC
, xx
, yy
, ww
, hh
, start
, end
);
557 CalcBoundingBox (x
, y
);
558 CalcBoundingBox (x
+ width
, y
+ height
);
561 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
563 wxCHECK_RET( Ok(), wxT("invalid window dc") );
565 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
566 XDrawPoint( (Display
*) m_display
, (Window
) m_window
,
567 (GC
) m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
569 CalcBoundingBox (x
, y
);
572 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
574 wxCHECK_RET( Ok(), wxT("invalid window dc") );
576 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
579 XPoint
*xpoints
= new XPoint
[n
];
580 for (int i
= 0; i
< n
; i
++)
582 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
583 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
585 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
587 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
, 0 );
592 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
593 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
595 wxCHECK_RET( Ok(), wxT("invalid window dc") );
599 XPoint
*xpoints
= new XPoint
[n
+ 1];
601 for (i
= 0; i
< n
; i
++)
603 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
604 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
606 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
611 if (m_brush
.GetStyle() != wxTRANSPARENT
)
614 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
616 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
617 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
618 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
620 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
621 (GC
) m_textGC
, xpoints
, n
, Complex
, 0);
623 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
625 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
627 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
628 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
630 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
631 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
633 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
635 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
637 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
638 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
640 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
641 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
643 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
645 if (m_brush
.GetStyle() == wxSTIPPLE
)
647 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
648 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
649 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
651 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
652 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
654 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
658 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
659 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
663 if (m_pen
.GetStyle () != wxTRANSPARENT
)
665 // Close figure for XDrawLines
666 xpoints
[i
].x
= xpoints
[0].x
;
667 xpoints
[i
].y
= xpoints
[0].y
;
669 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
+ 1, 0);
676 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
678 wxCHECK_RET( Ok(), wxT("invalid window dc") );
680 wxCoord xx
= XLOG2DEV(x
);
681 wxCoord yy
= YLOG2DEV(y
);
682 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
683 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
685 // CMB: draw nothing if transformed w or h is 0
686 if (ww
== 0 || hh
== 0) return;
688 // CMB: handle -ve width and/or height
689 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
690 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
694 if (m_brush
.GetStyle() != wxTRANSPARENT
)
696 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
698 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
699 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
700 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
702 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
703 (GC
) m_textGC
, xx
, yy
, ww
, hh
);
705 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
707 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
709 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
710 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
712 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
713 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
715 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
717 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
719 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
720 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
722 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
723 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
725 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
727 if (m_brush
.GetStyle() == wxSTIPPLE
)
729 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
730 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
731 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
733 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
734 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
736 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
740 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
741 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
745 if (m_pen
.GetStyle () != wxTRANSPARENT
)
747 XDrawRectangle( (Display
*) m_display
, (Window
) m_window
,
748 (GC
) m_penGC
, xx
, yy
, ww
, hh
);
752 CalcBoundingBox( x
, y
);
753 CalcBoundingBox( x
+ width
, y
+ height
);
754 wxLogDebug("Drawing rectangle at %d, %d (%dx%d)", x
, y
, width
, height
);
757 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
762 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
764 wxCHECK_RET( Ok(), wxT("invalid window dc") );
766 wxCoord xx
= XLOG2DEV(x
);
767 wxCoord yy
= YLOG2DEV(y
);
768 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
769 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
771 // CMB: handle -ve width and/or height
772 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
773 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
777 if (m_brush
.GetStyle() != wxTRANSPARENT
)
779 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
781 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
782 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
783 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
785 XFillArc( (Display
*) m_display
, (Window
) m_window
,
786 (GC
) m_textGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
788 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
790 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
792 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
793 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
795 XFillArc( (Display
*) m_display
, (Window
) m_window
,
796 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
798 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
800 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
802 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
803 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
805 XFillArc( (Display
*) m_display
, (Window
) m_window
,
806 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
808 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
810 if (m_brush
.GetStyle() == wxSTIPPLE
)
812 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
813 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
814 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
816 XFillArc( (Display
*) m_display
, (Window
) m_window
,
817 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
819 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
823 XFillArc( (Display
*) m_display
, (Window
) m_window
,
824 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
828 if (m_pen
.GetStyle () != wxTRANSPARENT
)
830 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
831 (GC
) m_penGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
835 CalcBoundingBox( x
, y
);
836 CalcBoundingBox( x
+ width
, y
+ height
);
839 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
843 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
844 wxCoord x
, wxCoord y
,
847 wxCHECK_RET( Ok(), wxT("invalid window dc") );
849 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
852 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
854 /* scale/translate size and position */
855 int xx
= XLOG2DEV(x
);
856 int yy
= YLOG2DEV(y
);
858 int w
= bitmap
.GetWidth();
859 int h
= bitmap
.GetHeight();
861 CalcBoundingBox( x
, y
);
862 CalcBoundingBox( x
+ w
, y
+ h
);
864 if (!m_window
) return;
866 int ww
= XLOG2DEVREL(w
);
867 int hh
= YLOG2DEVREL(h
);
869 /* compare to current clipping region */
870 if (!m_currentClippingRegion
.IsNull())
872 wxRegion
tmp( xx
,yy
,ww
,hh
);
873 tmp
.Intersect( m_currentClippingRegion
);
878 /* scale bitmap if required */
880 if ((w
!= ww
) || (h
!= hh
))
882 wxImage
image( bitmap
);
883 image
.Rescale( ww
, hh
);
885 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
887 use_bitmap
= image
.ConvertToBitmap();
894 /* apply mask if any */
895 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
896 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
900 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
901 if (!m_currentClippingRegion
.IsNull())
904 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
905 GdkGC
*gc
= gdk_gc_new( new_mask
);
907 gdk_gc_set_foreground( gc
, &col
);
908 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
910 gdk_gc_set_background( gc
, &col
);
912 gdk_gc_set_foreground( gc
, &col
);
913 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
914 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
915 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
916 gdk_gc_set_stipple( gc
, mask
);
917 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
924 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
926 gdk_gc_set_clip_mask( m_textGC
, mask
);
927 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
932 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
934 gdk_gc_set_clip_mask( m_penGC
, mask
);
935 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
938 gdk_bitmap_unref( new_mask
);
941 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
942 drawing a mono-bitmap (XBitmap) we use the current text GC */
944 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
946 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
948 /* remove mask again if any */
953 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
954 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
955 if (!m_currentClippingRegion
.IsNull())
956 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
960 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
961 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
962 if (!m_currentClippingRegion
.IsNull())
963 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
969 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
970 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
971 wxCoord xsrcMask
, wxCoord ysrcMask
)
973 /* this is the nth try to get this utterly useless function to
974 work. it now completely ignores the scaling or translation
975 of the source dc, but scales correctly on the target dc and
976 knows about possible mask information in a memory dc. */
978 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
980 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
982 if (!m_window
) return FALSE
;
984 // transform the source DC coords to the device ones
985 xsrc
= source
->XLOG2DEV(xsrc
);
986 ysrc
= source
->YLOG2DEV(ysrc
);
988 wxClientDC
*srcDC
= (wxClientDC
*)source
;
989 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
991 bool use_bitmap_method
= FALSE
;
992 bool is_mono
= FALSE
;
994 /* TODO: use the mask origin when drawing transparently */
995 if (xsrcMask
== -1 && ysrcMask
== -1)
997 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1001 if (srcDC
->m_isMemDC
)
1003 if (!memDC
->m_selected
.Ok()) return FALSE
;
1005 /* we use the "XCopyArea" way to copy a memory dc into
1006 y different window if the memory dc BOTH
1007 a) doesn't have any mask or its mask isn't used
1011 if (useMask
&& (memDC
->m_selected
.GetMask()))
1013 /* we HAVE TO use the direct way for memory dcs
1014 that have mask since the XCopyArea doesn't know
1016 use_bitmap_method
= TRUE
;
1018 else if (memDC
->m_selected
.GetDepth() == 1)
1020 /* we HAVE TO use the direct way for memory dcs
1021 that are bitmaps because XCopyArea doesn't cope
1022 with different bit depths */
1024 use_bitmap_method
= TRUE
;
1026 else if ((xsrc
== 0) && (ysrc
== 0) &&
1027 (width
== memDC
->m_selected
.GetWidth()) &&
1028 (height
== memDC
->m_selected
.GetHeight()))
1030 /* we SHOULD use the direct way if all of the bitmap
1031 in the memory dc is copied in which case XCopyArea
1032 wouldn't be able able to boost performace by reducing
1033 the area to be scaled */
1034 use_bitmap_method
= TRUE
;
1038 use_bitmap_method
= FALSE
;
1042 CalcBoundingBox( xdest
, ydest
);
1043 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1045 /* scale/translate size and position */
1046 wxCoord xx
= XLOG2DEV(xdest
);
1047 wxCoord yy
= YLOG2DEV(ydest
);
1049 wxCoord ww
= XLOG2DEVREL(width
);
1050 wxCoord hh
= YLOG2DEVREL(height
);
1052 /* compare to current clipping region */
1053 if (!m_currentClippingRegion
.IsNull())
1055 wxRegion
tmp( xx
,yy
,ww
,hh
);
1056 tmp
.Intersect( m_currentClippingRegion
);
1061 int old_logical_func
= m_logicalFunction
;
1062 SetLogicalFunction( logical_func
);
1064 if (use_bitmap_method
)
1066 /* scale/translate bitmap size */
1067 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1068 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1070 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1071 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1073 /* scale bitmap if required */
1074 wxBitmap use_bitmap
;
1076 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1078 wxImage
image( memDC
->m_selected
);
1079 image
= image
.Scale( bm_ww
, bm_hh
);
1082 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
1084 use_bitmap
= image
.ConvertToBitmap();
1088 use_bitmap
= memDC
->m_selected
;
1091 /* apply mask if any */
1092 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1093 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1095 if (useMask
&& mask
)
1097 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1098 if (!m_currentClippingRegion
.IsNull())
1101 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1102 GdkGC
*gc
= gdk_gc_new( new_mask
);
1104 gdk_gc_set_foreground( gc
, &col
);
1105 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1107 gdk_gc_set_background( gc
, &col
);
1109 gdk_gc_set_foreground( gc
, &col
);
1110 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1111 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1112 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1113 gdk_gc_set_stipple( gc
, mask
);
1114 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1121 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1123 gdk_gc_set_clip_mask( m_textGC
, mask
);
1124 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1129 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1131 gdk_gc_set_clip_mask( m_penGC
, mask
);
1132 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1135 gdk_bitmap_unref( new_mask
);
1138 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1139 drawing a mono-bitmap (XBitmap) we use the current text GC */
1142 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1144 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1146 /* remove mask again if any */
1147 if (useMask
&& mask
)
1151 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1152 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1153 if (!m_currentClippingRegion
.IsNull())
1154 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1158 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1159 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1160 if (!m_currentClippingRegion
.IsNull())
1161 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1165 else /* use_bitmap_method */
1167 if ((width
!= ww
) || (height
!= hh
))
1169 /* draw source window into a bitmap as we cannot scale
1170 a window in contrast to a bitmap. this would actually
1171 work with memory dcs as well, but we'd lose the mask
1172 information and waste one step in this process since
1173 a memory already has a bitmap. all this is slightly
1174 inefficient as we could take an XImage directly from
1175 an X window, but we'd then also have to care that
1176 the window is not outside the screen (in which case
1177 we'd get a BadMatch or what not).
1178 Is a double XGetImage and combined XGetPixel and
1179 XPutPixel really faster? I'm not sure. look at wxXt
1180 for a different implementation of the same problem. */
1182 wxBitmap
bitmap( width
, height
);
1184 /* copy including child window contents */
1185 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1186 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1188 xsrc
, ysrc
, width
, height
);
1189 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1192 wxImage
image( bitmap
);
1193 image
= image
.Scale( ww
, hh
);
1195 /* convert to bitmap */
1196 bitmap
= image
.ConvertToBitmap();
1198 /* draw scaled bitmap */
1199 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1204 /* No scaling and not a memory dc with a mask either */
1206 /* copy including child window contents */
1207 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1208 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1210 xsrc
, ysrc
, width
, height
);
1211 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1215 SetLogicalFunction( old_logical_func
);
1222 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1224 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1226 if (!m_window
) return;
1228 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1230 wxCHECK_RET( xfont
, wxT("invalid font") );
1235 XCharStruct overall_return
;
1237 int slen
= text
.Length();
1240 (void)XTextExtents((XFontStruct
*) xfont
, (char*) (const char*) text
, slen
, &direction
,
1241 &ascent
, &descent
, &overall_return
);
1243 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1244 wxCoord height
= font
->ascent
+ font
->descent
;
1246 if ( m_backgroundMode
== wxSOLID
)
1248 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1249 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1250 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1254 XSetFont( (Display
*) m_display
, (GC
) m_textGC
, xfont
->fid
);
1255 if ((xfont
->min_byte1
== 0) && (xfont
->max_byte1
== 0))
1257 XDrawString( (Display
*) m_display
, (Window
) m_window
,
1258 (GC
) m_textGC
, x
, y
+ ascent
, text
.c_str(), text
.Len() );
1259 wxLogDebug("Drawing text %s at %d, %d", text
.c_str(), x
, y
);
1263 if (m_font
.GetUnderlined())
1265 wxCoord ul_y
= y
+ font
->ascent
;
1266 if (font
->descent
> 0) ul_y
++;
1267 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1270 width
= wxCoord(width
/ m_scaleX
);
1271 height
= wxCoord(height
/ m_scaleY
);
1273 CalcBoundingBox (x
+ width
, y
+ height
);
1274 CalcBoundingBox (x
, y
);
1278 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1283 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1284 wxCoord
*descent
, wxCoord
*externalLeading
,
1285 wxFont
*font
) const
1287 wxCHECK_RET( Ok(), "invalid dc" );
1289 wxFont fontToUse
= m_font
;
1290 if (font
) fontToUse
= *font
;
1292 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
1294 XFontStruct
*xfont
= (XFontStruct
*) fontToUse
.GetFontStruct( m_scaleY
, m_display
);
1296 wxCHECK_RET( xfont
, wxT("invalid font") );
1298 int direction
, ascent
, descent2
;
1299 XCharStruct overall
;
1301 XTextExtents( xfont
, string
.c_str(), string
.Len(), &direction
,
1302 &ascent
, &descent2
, &overall
);
1305 *width
= (wxCoord
)( overall
.width
/ m_scaleX
);
1307 *height
= (wxCoord
)((ascent
+ descent2
) / m_scaleY
);
1309 *descent
= (wxCoord
)(descent2
/ m_scaleY
);
1310 if (externalLeading
)
1311 *externalLeading
= 0; // ??
1314 wxCoord
wxWindowDC::GetCharWidth() const
1316 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1318 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1320 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1322 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1324 int direction
, ascent
, descent
;
1325 XCharStruct overall
;
1327 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1329 return (wxCoord
)(overall
.width
/ m_scaleX
);
1332 wxCoord
wxWindowDC::GetCharHeight() const
1334 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1336 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1338 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1340 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1342 int direction
, ascent
, descent
;
1343 XCharStruct overall
;
1345 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1347 return (wxCoord
)((ascent
+descent
) / m_scaleY
);
1350 void wxWindowDC::Clear()
1352 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1354 if (!m_window
) return;
1356 /* - we either are a memory dc or have a window as the
1357 owner. anything else shouldn't happen.
1358 - we don't use gdk_window_clear() as we don't set
1359 the window's background colour anymore. it is too
1360 much pain to keep the DC's and the window's back-
1361 ground colour in synch. */
1366 m_owner
->GetSize( &width
, &height
);
1367 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1374 GetSize( &width
, &height
);
1375 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1380 void wxWindowDC::SetFont( const wxFont
&font
)
1382 wxCHECK_RET( Ok(), "invalid dc" );
1387 void wxWindowDC::SetPen( const wxPen
&pen
)
1389 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1391 if (m_pen
== pen
) return;
1395 if (!m_pen
.Ok()) return;
1397 if (!m_window
) return;
1399 int width
= m_pen
.GetWidth();
1402 // CMB: if width is non-zero scale it with the dc
1407 // X doesn't allow different width in x and y and so we take
1410 ( fabs((double) XLOG2DEVREL(width
)) +
1411 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1415 static const wxX11Dash dotted
[] = {1, 1};
1416 static const wxX11Dash short_dashed
[] = {2, 2};
1417 static const wxX11Dash long_dashed
[] = {2, 4};
1418 static const wxX11Dash dotted_dashed
[] = {3, 3, 1, 3};
1420 // We express dash pattern in pen width unit, so we are
1421 // independent of zoom factor and so on...
1423 const wxX11Dash
*req_dash
;
1425 int lineStyle
= LineSolid
;
1426 switch (m_pen
.GetStyle())
1430 lineStyle
= LineOnOffDash
;
1431 req_nb_dash
= m_pen
.GetDashCount();
1432 req_dash
= (wxX11Dash
*)m_pen
.GetDash();
1437 lineStyle
= LineOnOffDash
;
1444 lineStyle
= LineOnOffDash
;
1446 req_dash
= long_dashed
;
1451 lineStyle
= LineOnOffDash
;
1453 req_dash
= short_dashed
;
1458 // lineStyle = LineDoubleDash;
1459 lineStyle
= LineOnOffDash
;
1461 req_dash
= dotted_dashed
;
1466 case wxSTIPPLE_MASK_OPAQUE
:
1471 lineStyle
= LineSolid
;
1472 req_dash
= (wxX11Dash
*)NULL
;
1478 int capStyle
= CapRound
;
1479 switch (m_pen
.GetCap())
1481 case wxCAP_PROJECTING
: { capStyle
= CapProjecting
; break; }
1482 case wxCAP_BUTT
: { capStyle
= CapButt
; break; }
1489 capStyle
= CapNotLast
;
1493 capStyle
= CapRound
;
1499 int joinStyle
= JoinRound
;
1500 switch (m_pen
.GetJoin())
1502 case wxJOIN_BEVEL
: { joinStyle
= JoinBevel
; break; }
1503 case wxJOIN_MITER
: { joinStyle
= JoinMiter
; break; }
1505 default: { joinStyle
= JoinRound
; break; }
1508 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1510 m_pen
.GetColour().CalcPixel( m_cmap
);
1511 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
1514 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1516 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1518 if (m_brush
== brush
) return;
1522 if (!m_brush
.Ok()) return;
1524 if (!m_window
) return;
1526 m_brush
.GetColour().CalcPixel( m_cmap
);
1527 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
1529 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
1531 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1533 if (m_brush
.GetStipple()->GetPixmap())
1535 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillTiled
);
1536 XSetTile( (Display
*) m_display
, (GC
) m_brushGC
, (Pixmap
) m_brush
.GetStipple()->GetPixmap() );
1540 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1541 // XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1545 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1547 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillOpaqueStippled
);
1548 // XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1551 if (IS_HATCH(m_brush
.GetStyle()))
1553 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1554 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1555 XSetStipple( (Display
*) m_display
, (GC
) m_brushGC
, hatches
[num
] );
1559 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1561 /* CMB 21/7/98: Added SetBackground. Sets background brush
1562 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1564 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1566 if (m_backgroundBrush
== brush
) return;
1568 m_backgroundBrush
= brush
;
1570 if (!m_backgroundBrush
.Ok()) return;
1572 if (!m_window
) return;
1574 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1575 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, m_backgroundBrush
.GetColour().GetPixel() );
1576 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, m_backgroundBrush
.GetColour().GetPixel() );
1577 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1578 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1580 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
1582 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1584 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1586 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillTiled
);
1587 XSetTile( (Display
*) m_display
, (GC
) m_bgGC
, (Pixmap
) m_backgroundBrush
.GetStipple()->GetPixmap() );
1591 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1592 // XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
1596 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1598 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1599 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1600 XSetStipple( (Display
*) m_display
, (GC
) m_bgGC
, hatches
[num
] );
1604 void wxWindowDC::SetLogicalFunction( int function
)
1606 wxCHECK_RET( Ok(), "invalid dc" );
1610 if (m_logicalFunction
== function
)
1613 // VZ: shouldn't this be a CHECK?
1620 x_function
= GXclear
;
1626 x_function
= GXinvert
;
1629 x_function
= GXorReverse
;
1632 x_function
= GXandReverse
;
1641 x_function
= GXandInverted
;
1644 x_function
= GXnoop
;
1650 x_function
= GXequiv
;
1653 x_function
= GXcopyInverted
;
1656 x_function
= GXorInverted
;
1659 x_function
= GXnand
;
1666 x_function
= GXcopy
;
1670 XSetFunction( (Display
*) m_display
, (GC
) m_penGC
, x_function
);
1671 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, x_function
);
1673 // to stay compatible with wxMSW, we don't apply ROPs to the text
1674 // operations (i.e. DrawText/DrawRotatedText).
1675 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1676 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, x_function
);
1678 m_logicalFunction
= function
;
1681 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1683 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1685 // don't set m_textForegroundColour to an invalid colour as we'd crash
1686 // later then (we use m_textForegroundColour.GetColor() without checking
1688 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1691 m_textForegroundColour
= col
;
1695 m_textForegroundColour
.CalcPixel( m_cmap
);
1696 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
1700 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1702 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1705 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1708 m_textBackgroundColour
= col
;
1712 m_textBackgroundColour
.CalcPixel( m_cmap
);
1713 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
1717 void wxWindowDC::SetBackgroundMode( int mode
)
1719 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1721 m_backgroundMode
= mode
;
1723 if (!m_window
) return;
1725 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1726 // transparent/solid background mode
1728 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1730 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
,
1731 (m_backgroundMode
== wxTRANSPARENT
) ? FillStippled
: FillOpaqueStippled
);
1735 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1741 /* Use GetXColormap */
1742 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1743 (Colormap
) palette
.GetXColormap());
1745 /* Use wxGetMainColormap */
1746 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1747 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1752 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1754 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1756 if (!m_window
) return;
1759 rect
.x
= XLOG2DEV(x
);
1760 rect
.y
= YLOG2DEV(y
);
1761 rect
.width
= XLOG2DEVREL(width
);
1762 rect
.height
= YLOG2DEVREL(height
);
1764 if (!m_currentClippingRegion
.IsNull())
1765 m_currentClippingRegion
.Intersect( rect
);
1767 m_currentClippingRegion
.Union( rect
);
1769 #if USE_PAINT_REGION
1770 if (!m_paintClippingRegion
.IsNull())
1771 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1774 wxCoord xx
, yy
, ww
, hh
;
1775 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1776 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1778 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1779 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1780 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1781 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1784 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
1786 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1790 DestroyClippingRegion();
1794 if (!m_window
) return;
1796 if (!m_currentClippingRegion
.IsNull())
1797 m_currentClippingRegion
.Intersect( region
);
1799 m_currentClippingRegion
.Union( region
);
1801 #if USE_PAINT_REGION
1802 if (!m_paintClippingRegion
.IsNull())
1803 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1806 wxCoord xx
, yy
, ww
, hh
;
1807 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1808 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1810 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1811 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1812 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1813 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1816 void wxWindowDC::DestroyClippingRegion()
1818 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1820 wxDC::DestroyClippingRegion();
1822 m_currentClippingRegion
.Clear();
1824 #if USE_PAINT_REGION
1825 if (!m_paintClippingRegion
.IsEmpty())
1826 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1829 if (!m_window
) return;
1831 if (m_currentClippingRegion
.IsEmpty())
1833 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
1834 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
1835 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
1836 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
1840 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1841 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1842 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1843 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1847 void wxWindowDC::Destroy()
1849 if (m_penGC
) wxFreePoolGC( (GC
) m_penGC
);
1851 if (m_brushGC
) wxFreePoolGC( (GC
) m_brushGC
);
1853 if (m_textGC
) wxFreePoolGC( (GC
) m_textGC
);
1855 if (m_bgGC
) wxFreePoolGC( (GC
) m_bgGC
);
1859 void wxWindowDC::ComputeScaleAndOrigin()
1861 /* CMB: copy scale to see if it changes */
1862 double origScaleX
= m_scaleX
;
1863 double origScaleY
= m_scaleY
;
1865 wxDC::ComputeScaleAndOrigin();
1867 /* CMB: if scale has changed call SetPen to recalulate the line width */
1868 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1871 /* this is a bit artificial, but we need to force wxDC to think
1872 the pen has changed */
1879 wxSize
wxWindowDC::GetPPI() const
1881 return wxSize(100, 100);
1884 int wxWindowDC::GetDepth() const
1886 wxFAIL_MSG(wxT("not implemented"));
1891 // ----------------------------------------------------------------------------
1893 // ----------------------------------------------------------------------------
1895 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
1897 wxPaintDC::wxPaintDC(wxWindow
* win
)
1900 #if USE_PAINT_REGION
1901 if (!win
->GetClipPaintRegion())
1904 m_paintClippingRegion
= win
->GetUpdateRegion();
1905 Region region
= (Region
) m_paintClippingRegion
.GetX11Region();
1908 m_paintClippingRegion
= win
->GetUpdateRegion();
1909 Region region2
= (Region
) m_paintClippingRegion
.GetX11Region();
1912 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1914 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, region2
);
1915 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, region2
);
1916 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, region2
);
1917 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, region2
);
1920 #endif // USE_PAINT_REGION
1923 //-----------------------------------------------------------------------------
1925 //-----------------------------------------------------------------------------
1927 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
1929 wxClientDC::wxClientDC( wxWindow
*win
)
1932 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
1935 void wxClientDC::DoGetSize(int *width
, int *height
) const
1937 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
1939 m_owner
->GetClientSize( width
, height
);
1942 // ----------------------------------------------------------------------------
1944 // ----------------------------------------------------------------------------
1946 class wxDCModule
: public wxModule
1953 DECLARE_DYNAMIC_CLASS(wxDCModule
)
1956 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
1958 bool wxDCModule::OnInit()
1964 void wxDCModule::OnExit()