]>
git.saurik.com Git - wxWidgets.git/blob - src/x11/dcclient.cpp
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
);
229 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
231 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_MONO
);
232 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_MONO
);
233 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_MONO
);
234 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_MONO
);
238 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_COLOUR
);
239 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_COLOUR
);
240 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_COLOUR
);
241 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_COLOUR
);
244 /* background colour */
245 m_backgroundBrush
= *wxWHITE_BRUSH
;
246 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
247 unsigned long bg_col
= m_backgroundBrush
.GetColour().GetPixel();
250 m_textForegroundColour
.CalcPixel( m_cmap
);
251 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
253 m_textBackgroundColour
.CalcPixel( m_cmap
);
254 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
256 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillSolid
);
259 // By default, draw transparently
260 GrSetGCUseBackground((GC
) m_textGC
, FALSE
);
264 m_pen
.GetColour().CalcPixel( m_cmap
);
265 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
266 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, bg_col
);
268 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, 0, LineSolid
, CapNotLast
, JoinRound
);
271 m_brush
.GetColour().CalcPixel( m_cmap
);
272 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
273 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, bg_col
);
275 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
278 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
279 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
281 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
284 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, GXcopy
);
285 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, GXcopy
);
286 XSetFunction( (Display
*) m_display
, (GC
)m_penGC
, GXcopy
);
289 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
290 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
291 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
292 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
296 int xscreen
= DefaultScreen( (Display
*) m_display
);
297 Window xroot
= RootWindow( (Display
*) m_display
, xscreen
);
299 hatch_bitmap
= hatches
;
300 hatch_bitmap
[0] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, bdiag_bits
, bdiag_width
, bdiag_height
);
301 hatch_bitmap
[1] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cdiag_bits
, cdiag_width
, cdiag_height
);
302 hatch_bitmap
[2] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, fdiag_bits
, fdiag_width
, fdiag_height
);
303 hatch_bitmap
[3] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cross_bits
, cross_width
, cross_height
);
304 hatch_bitmap
[4] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, horiz_bits
, horiz_width
, horiz_height
);
305 hatch_bitmap
[5] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, verti_bits
, verti_width
, verti_height
);
309 void wxWindowDC::DoGetSize( int* width
, int* height
) const
311 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
313 m_owner
->GetSize(width
, height
);
316 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
317 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
319 wxFAIL_MSG("not implemented");
322 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
324 // Generic (and therefore rather inefficient) method.
325 // Could be improved.
327 wxBitmap
bitmap(1, 1);
328 memdc
.SelectObject(bitmap
);
329 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
330 memdc
.SelectObject(wxNullBitmap
);
331 wxImage
image(bitmap
);
332 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
336 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
338 wxCHECK_RET( Ok(), wxT("invalid window dc") );
340 if (m_pen
.GetStyle() != wxTRANSPARENT
)
343 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
344 (GC
) m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
346 CalcBoundingBox(x1
, y1
);
347 CalcBoundingBox(x2
, y2
);
351 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
355 if (m_pen
.GetStyle() != wxTRANSPARENT
)
360 wxCoord xx
= XLOG2DEV(x
);
361 wxCoord yy
= YLOG2DEV(y
);
364 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
365 (GC
) m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
366 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
367 (GC
) m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
372 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
374 wxCHECK_RET( Ok(), wxT("invalid window dc") );
376 wxCoord xx1
= XLOG2DEV(x1
);
377 wxCoord yy1
= YLOG2DEV(y1
);
378 wxCoord xx2
= XLOG2DEV(x2
);
379 wxCoord yy2
= YLOG2DEV(y2
);
380 wxCoord xxc
= XLOG2DEV(xc
);
381 wxCoord yyc
= YLOG2DEV(yc
);
382 double dx
= xx1
- xxc
;
383 double dy
= yy1
- yyc
;
384 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
385 wxCoord r
= (wxCoord
)radius
;
386 double radius1
, radius2
;
388 if (xx1
== xx2
&& yy1
== yy2
)
396 radius1
= radius2
= 0.0;
400 radius1
= (xx1
- xxc
== 0) ?
401 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
402 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
403 radius2
= (xx2
- xxc
== 0) ?
404 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
405 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
407 wxCoord alpha1
= wxCoord(radius1
* 64.0);
408 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
409 while (alpha2
<= 0) alpha2
+= 360*64;
410 while (alpha1
> 360*64) alpha1
-= 360*64;
414 if (m_brush
.GetStyle() != wxTRANSPARENT
)
416 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
418 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
419 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
420 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
422 XFillArc( (Display
*) m_display
, (Window
) m_window
,
423 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
425 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
427 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
429 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
430 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
432 XFillArc( (Display
*) m_display
, (Window
) m_window
,
433 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
435 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
437 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
439 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
440 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
442 XFillArc( (Display
*) m_display
, (Window
) m_window
,
443 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
445 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
447 if (m_brush
.GetStyle() == wxSTIPPLE
)
449 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
450 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
451 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
453 XFillArc( (Display
*) m_display
, (Window
) m_window
,
454 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
456 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
460 XFillArc( (Display
*) m_display
, (Window
) m_window
,
461 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
465 if (m_pen
.GetStyle() != wxTRANSPARENT
)
467 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
468 (GC
) m_penGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
470 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
471 (GC
) m_penGC
, xx1
, yy1
, xxc
, yyc
);
473 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
474 (GC
) m_penGC
, xxc
, yyc
, xx2
, yy2
);
478 CalcBoundingBox (x1
, y1
);
479 CalcBoundingBox (x2
, y2
);
482 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
484 wxCHECK_RET( Ok(), wxT("invalid window dc") );
486 wxCoord xx
= XLOG2DEV(x
);
487 wxCoord yy
= YLOG2DEV(y
);
488 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
489 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
491 // CMB: handle -ve width and/or height
492 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
493 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
497 wxCoord start
= wxCoord(sa
* 64.0);
498 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
500 if (m_brush
.GetStyle() != wxTRANSPARENT
)
502 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
504 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
505 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
506 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
508 XFillArc( (Display
*) m_display
, (Window
) m_window
,
509 (GC
) m_textGC
, xx
, yy
, ww
, hh
, start
, end
);
511 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
513 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
515 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
516 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
518 XFillArc( (Display
*) m_display
, (Window
) m_window
,
519 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
521 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
523 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
525 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
526 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
528 XFillArc( (Display
*) m_display
, (Window
) m_window
,
529 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
531 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
533 if (m_brush
.GetStyle() == wxSTIPPLE
)
535 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
536 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
537 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
539 XFillArc( (Display
*) m_display
, (Window
) m_window
,
540 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
542 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
546 XFillArc( (Display
*) m_display
, (Window
) m_window
,
547 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
551 if (m_pen
.GetStyle() != wxTRANSPARENT
)
553 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
554 (GC
) m_penGC
, xx
, yy
, ww
, hh
, start
, end
);
558 CalcBoundingBox (x
, y
);
559 CalcBoundingBox (x
+ width
, y
+ height
);
562 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
564 wxCHECK_RET( Ok(), wxT("invalid window dc") );
566 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
567 XDrawPoint( (Display
*) m_display
, (Window
) m_window
,
568 (GC
) m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
570 CalcBoundingBox (x
, y
);
573 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
575 wxCHECK_RET( Ok(), wxT("invalid window dc") );
577 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
580 XPoint
*xpoints
= new XPoint
[n
];
581 for (int i
= 0; i
< n
; i
++)
583 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
584 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
586 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
588 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
, 0 );
593 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
594 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
596 wxCHECK_RET( Ok(), wxT("invalid window dc") );
600 XPoint
*xpoints
= new XPoint
[n
+ 1];
602 for (i
= 0; i
< n
; i
++)
604 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
605 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
607 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
612 if (m_brush
.GetStyle() != wxTRANSPARENT
)
615 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
617 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
618 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
619 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
621 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
622 (GC
) m_textGC
, xpoints
, n
, Complex
, 0);
624 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
626 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
628 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
629 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
631 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
632 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
634 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
636 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
638 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
639 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
641 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
642 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
644 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
646 if (m_brush
.GetStyle() == wxSTIPPLE
)
648 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
649 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
650 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
652 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
653 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
655 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
659 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
660 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
664 if (m_pen
.GetStyle () != wxTRANSPARENT
)
666 // Close figure for XDrawLines
667 xpoints
[i
].x
= xpoints
[0].x
;
668 xpoints
[i
].y
= xpoints
[0].y
;
670 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
+ 1, 0);
677 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
679 wxCHECK_RET( Ok(), wxT("invalid window dc") );
681 wxCoord xx
= XLOG2DEV(x
);
682 wxCoord yy
= YLOG2DEV(y
);
683 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
684 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
686 // CMB: draw nothing if transformed w or h is 0
687 if (ww
== 0 || hh
== 0) return;
689 // CMB: handle -ve width and/or height
690 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
691 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
695 if (m_brush
.GetStyle() != wxTRANSPARENT
)
697 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
699 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
700 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
701 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
703 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
704 (GC
) m_textGC
, xx
, yy
, ww
, hh
);
706 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
708 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
710 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
711 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
713 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
714 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
716 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
718 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
720 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
721 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
723 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
724 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
726 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
728 if (m_brush
.GetStyle() == wxSTIPPLE
)
730 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
731 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
732 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
734 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
735 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
737 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
741 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
742 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
746 if (m_pen
.GetStyle () != wxTRANSPARENT
)
748 XDrawRectangle( (Display
*) m_display
, (Window
) m_window
,
749 (GC
) m_penGC
, xx
, yy
, ww
-1, hh
-1 );
753 CalcBoundingBox( x
, y
);
754 CalcBoundingBox( x
+ width
, y
+ 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") );
851 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
853 /* scale/translate size and position */
854 int xx
= XLOG2DEV(x
);
855 int yy
= YLOG2DEV(y
);
857 int w
= bitmap
.GetWidth();
858 int h
= bitmap
.GetHeight();
860 CalcBoundingBox( x
, y
);
861 CalcBoundingBox( x
+ w
, y
+ h
);
863 if (!m_window
) return;
865 int ww
= XLOG2DEVREL(w
);
866 int hh
= YLOG2DEVREL(h
);
868 /* compare to current clipping region */
869 if (!m_currentClippingRegion
.IsNull())
871 wxRegion
tmp( xx
,yy
,ww
,hh
);
872 tmp
.Intersect( m_currentClippingRegion
);
877 /* scale bitmap if required */
879 if ((w
!= ww
) || (h
!= hh
))
881 wxImage
image( bitmap
);
882 image
.Rescale( ww
, hh
);
885 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
888 use_bitmap
= image
.ConvertToBitmap();
895 /* apply mask if any */
896 WXPixmap mask
= NULL
;
897 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
901 WXPixmap new_mask
= NULL
;
903 if (!m_currentClippingRegion
.IsNull())
906 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
907 GdkGC
*gc
= gdk_gc_new( new_mask
);
909 gdk_gc_set_foreground( gc
, &col
);
910 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
912 gdk_gc_set_background( gc
, &col
);
914 gdk_gc_set_foreground( gc
, &col
);
915 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
916 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
917 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
918 gdk_gc_set_stipple( gc
, mask
);
919 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
926 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, (Pixmap
) new_mask
);
928 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, (Pixmap
) mask
);
929 XSetClipOrigin( (Display
*) m_display
, (GC
) m_textGC
, xx
, yy
);
934 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, (Pixmap
) new_mask
);
936 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, (Pixmap
) mask
);
937 XSetClipOrigin( (Display
*) m_display
, (GC
) m_penGC
, xx
, yy
);
941 XFreePixmap( (Display
*) m_display
, (Pixmap
) new_mask
);
945 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
946 drawing a mono-bitmap (XBitmap) we use the current text GC */
948 XCopyPlane( (Display
*) m_display
, (Pixmap
) use_bitmap
.GetBitmap(), (Window
) m_window
,
949 (GC
) m_textGC
, 0, 0, w
, h
, xx
, yy
, 1 );
951 XCopyArea( (Display
*) m_display
, (Pixmap
) use_bitmap
.GetPixmap(), (Window
) m_window
,
952 (GC
) m_penGC
, 0, 0, w
, h
, xx
, yy
);
954 /* remove mask again if any */
959 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
960 XSetClipOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
961 if (!m_currentClippingRegion
.IsNull())
962 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
966 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
967 XSetClipOrigin( (Display
*) m_display
, (GC
) m_penGC
, 0, 0 );
968 if (!m_currentClippingRegion
.IsNull())
969 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
974 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
975 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
976 wxCoord xsrcMask
, wxCoord ysrcMask
)
978 /* this is the nth try to get this utterly useless function to
979 work. it now completely ignores the scaling or translation
980 of the source dc, but scales correctly on the target dc and
981 knows about possible mask information in a memory dc. */
983 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
985 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
987 if (!m_window
) return FALSE
;
989 // transform the source DC coords to the device ones
990 xsrc
= source
->XLOG2DEV(xsrc
);
991 ysrc
= source
->YLOG2DEV(ysrc
);
993 wxClientDC
*srcDC
= (wxClientDC
*)source
;
994 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
996 bool use_bitmap_method
= FALSE
;
997 bool is_mono
= FALSE
;
999 /* TODO: use the mask origin when drawing transparently */
1000 if (xsrcMask
== -1 && ysrcMask
== -1)
1002 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1006 if (srcDC
->m_isMemDC
)
1008 if (!memDC
->m_selected
.Ok()) return FALSE
;
1010 /* we use the "XCopyArea" way to copy a memory dc into
1011 y different window if the memory dc BOTH
1012 a) doesn't have any mask or its mask isn't used
1016 if (useMask
&& (memDC
->m_selected
.GetMask()))
1018 /* we HAVE TO use the direct way for memory dcs
1019 that have mask since the XCopyArea doesn't know
1021 use_bitmap_method
= TRUE
;
1023 else if (memDC
->m_selected
.GetDepth() == 1)
1025 /* we HAVE TO use the direct way for memory dcs
1026 that are bitmaps because XCopyArea doesn't cope
1027 with different bit depths */
1029 use_bitmap_method
= TRUE
;
1031 else if ((xsrc
== 0) && (ysrc
== 0) &&
1032 (width
== memDC
->m_selected
.GetWidth()) &&
1033 (height
== memDC
->m_selected
.GetHeight()))
1035 /* we SHOULD use the direct way if all of the bitmap
1036 in the memory dc is copied in which case XCopyArea
1037 wouldn't be able able to boost performace by reducing
1038 the area to be scaled */
1039 use_bitmap_method
= TRUE
;
1043 use_bitmap_method
= FALSE
;
1047 CalcBoundingBox( xdest
, ydest
);
1048 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1050 /* scale/translate size and position */
1051 wxCoord xx
= XLOG2DEV(xdest
);
1052 wxCoord yy
= YLOG2DEV(ydest
);
1054 wxCoord ww
= XLOG2DEVREL(width
);
1055 wxCoord hh
= YLOG2DEVREL(height
);
1057 /* compare to current clipping region */
1058 if (!m_currentClippingRegion
.IsNull())
1060 wxRegion
tmp( xx
,yy
,ww
,hh
);
1061 tmp
.Intersect( m_currentClippingRegion
);
1066 int old_logical_func
= m_logicalFunction
;
1067 SetLogicalFunction( logical_func
);
1069 if (use_bitmap_method
)
1071 /* scale/translate bitmap size */
1072 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1073 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1075 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1076 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1078 /* scale bitmap if required */
1079 wxBitmap use_bitmap
;
1081 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1083 wxImage
image( memDC
->m_selected
);
1084 image
= image
.Scale( bm_ww
, bm_hh
);
1087 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
1089 use_bitmap
= image
.ConvertToBitmap();
1093 use_bitmap
= memDC
->m_selected
;
1096 /* apply mask if any */
1097 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1098 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1100 if (useMask
&& mask
)
1102 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1103 if (!m_currentClippingRegion
.IsNull())
1106 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1107 GdkGC
*gc
= gdk_gc_new( new_mask
);
1109 gdk_gc_set_foreground( gc
, &col
);
1110 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1112 gdk_gc_set_background( gc
, &col
);
1114 gdk_gc_set_foreground( gc
, &col
);
1115 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1116 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1117 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1118 gdk_gc_set_stipple( gc
, mask
);
1119 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1126 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1128 gdk_gc_set_clip_mask( m_textGC
, mask
);
1129 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1134 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1136 gdk_gc_set_clip_mask( m_penGC
, mask
);
1137 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1140 gdk_bitmap_unref( new_mask
);
1143 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1144 drawing a mono-bitmap (XBitmap) we use the current text GC */
1147 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1149 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1151 /* remove mask again if any */
1152 if (useMask
&& mask
)
1156 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1157 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1158 if (!m_currentClippingRegion
.IsNull())
1159 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1163 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1164 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1165 if (!m_currentClippingRegion
.IsNull())
1166 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1170 else /* use_bitmap_method */
1172 if ((width
!= ww
) || (height
!= hh
))
1174 /* draw source window into a bitmap as we cannot scale
1175 a window in contrast to a bitmap. this would actually
1176 work with memory dcs as well, but we'd lose the mask
1177 information and waste one step in this process since
1178 a memory already has a bitmap. all this is slightly
1179 inefficient as we could take an XImage directly from
1180 an X window, but we'd then also have to care that
1181 the window is not outside the screen (in which case
1182 we'd get a BadMatch or what not).
1183 Is a double XGetImage and combined XGetPixel and
1184 XPutPixel really faster? I'm not sure. look at wxXt
1185 for a different implementation of the same problem. */
1187 wxBitmap
bitmap( width
, height
);
1189 /* copy including child window contents */
1190 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1191 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1193 xsrc
, ysrc
, width
, height
);
1194 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1197 wxImage
image( bitmap
);
1198 image
= image
.Scale( ww
, hh
);
1200 /* convert to bitmap */
1201 bitmap
= image
.ConvertToBitmap();
1203 /* draw scaled bitmap */
1204 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1209 /* No scaling and not a memory dc with a mask either */
1211 /* copy including child window contents */
1212 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1213 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1215 xsrc
, ysrc
, width
, height
);
1216 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1220 SetLogicalFunction( old_logical_func
);
1227 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1229 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1231 if (!m_window
) return;
1233 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1235 wxCHECK_RET( xfont
, wxT("invalid font") );
1241 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1242 wxCoord height
= font
->ascent
+ font
->descent
;
1244 if ( m_backgroundMode
== wxSOLID
)
1246 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1247 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1248 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1252 XSetFont( (Display
*) m_display
, (GC
) m_textGC
, xfont
->fid
);
1254 if ((xfont
->min_byte1
== 0) && (xfont
->max_byte1
== 0))
1257 XDrawString( (Display
*) m_display
, (Window
) m_window
,
1258 (GC
) m_textGC
, x
, y
+ XFontStructGetAscent(xfont
), text
.c_str(), text
.Len() );
1262 if (m_font
.GetUnderlined())
1264 wxCoord ul_y
= y
+ XFontStructGetAscent(font
);
1265 if (font
->descent
> 0) ul_y
++;
1266 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1269 width
= wxCoord(width
/ m_scaleX
);
1270 height
= wxCoord(height
/ m_scaleY
);
1272 CalcBoundingBox (x
+ width
, y
+ height
);
1273 CalcBoundingBox (x
, y
);
1277 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1282 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1283 wxCoord
*descent
, wxCoord
*externalLeading
,
1284 wxFont
*font
) const
1286 wxCHECK_RET( Ok(), "invalid dc" );
1288 wxFont fontToUse
= m_font
;
1289 if (font
) fontToUse
= *font
;
1291 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
1293 XFontStruct
*xfont
= (XFontStruct
*) fontToUse
.GetFontStruct( m_scaleY
, m_display
);
1295 wxCHECK_RET( xfont
, wxT("invalid font") );
1297 int direction
, ascent
, descent2
;
1298 XCharStruct overall
;
1300 XTextExtents( xfont
, (char*) string
.c_str(), string
.Len(), &direction
,
1301 &ascent
, &descent2
, &overall
);
1304 *width
= (wxCoord
)( overall
.width
/ m_scaleX
);
1306 *height
= (wxCoord
)((ascent
+ descent2
) / m_scaleY
);
1308 *descent
= (wxCoord
)(descent2
/ m_scaleY
);
1309 if (externalLeading
)
1310 *externalLeading
= 0; // ??
1313 wxCoord
wxWindowDC::GetCharWidth() const
1315 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1317 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1319 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1321 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1323 int direction
, ascent
, descent
;
1324 XCharStruct overall
;
1326 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1328 return (wxCoord
)(overall
.width
/ m_scaleX
);
1331 wxCoord
wxWindowDC::GetCharHeight() const
1333 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1335 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1337 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1339 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1341 int direction
, ascent
, descent
;
1342 XCharStruct overall
;
1344 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1346 return (wxCoord
)((ascent
+descent
) / m_scaleY
);
1349 void wxWindowDC::Clear()
1351 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1353 if (!m_window
) return;
1355 /* - we either are a memory dc or have a window as the
1356 owner. anything else shouldn't happen.
1357 - we don't use gdk_window_clear() as we don't set
1358 the window's background colour anymore. it is too
1359 much pain to keep the DC's and the window's back-
1360 ground colour in synch. */
1365 m_owner
->GetSize( &width
, &height
);
1366 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1373 GetSize( &width
, &height
);
1374 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1379 void wxWindowDC::SetFont( const wxFont
&font
)
1381 wxCHECK_RET( Ok(), "invalid dc" );
1386 void wxWindowDC::SetPen( const wxPen
&pen
)
1388 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1390 if (m_pen
== pen
) return;
1394 if (!m_pen
.Ok()) return;
1396 if (!m_window
) return;
1398 int width
= m_pen
.GetWidth();
1401 // CMB: if width is non-zero scale it with the dc
1406 // X doesn't allow different width in x and y and so we take
1409 ( fabs((double) XLOG2DEVREL(width
)) +
1410 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1414 static const wxX11Dash dotted
[] = {1, 1};
1415 static const wxX11Dash short_dashed
[] = {2, 2};
1416 static const wxX11Dash long_dashed
[] = {2, 4};
1417 static const wxX11Dash dotted_dashed
[] = {3, 3, 1, 3};
1419 // We express dash pattern in pen width unit, so we are
1420 // independent of zoom factor and so on...
1422 const wxX11Dash
*req_dash
;
1424 int lineStyle
= LineSolid
;
1425 switch (m_pen
.GetStyle())
1429 lineStyle
= LineOnOffDash
;
1430 req_nb_dash
= m_pen
.GetDashCount();
1431 req_dash
= (wxX11Dash
*)m_pen
.GetDash();
1436 lineStyle
= LineOnOffDash
;
1443 lineStyle
= LineOnOffDash
;
1445 req_dash
= long_dashed
;
1450 lineStyle
= LineOnOffDash
;
1452 req_dash
= short_dashed
;
1457 // lineStyle = LineDoubleDash;
1458 lineStyle
= LineOnOffDash
;
1460 req_dash
= dotted_dashed
;
1465 case wxSTIPPLE_MASK_OPAQUE
:
1470 lineStyle
= LineSolid
;
1471 req_dash
= (wxX11Dash
*)NULL
;
1477 int capStyle
= CapRound
;
1478 switch (m_pen
.GetCap())
1480 case wxCAP_PROJECTING
: { capStyle
= CapProjecting
; break; }
1481 case wxCAP_BUTT
: { capStyle
= CapButt
; break; }
1488 capStyle
= CapNotLast
;
1492 capStyle
= CapRound
;
1498 int joinStyle
= JoinRound
;
1499 switch (m_pen
.GetJoin())
1501 case wxJOIN_BEVEL
: { joinStyle
= JoinBevel
; break; }
1502 case wxJOIN_MITER
: { joinStyle
= JoinMiter
; break; }
1504 default: { joinStyle
= JoinRound
; break; }
1507 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1509 m_pen
.GetColour().CalcPixel( m_cmap
);
1510 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
1513 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1515 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1517 if (m_brush
== brush
) return;
1521 if (!m_brush
.Ok()) return;
1523 if (!m_window
) return;
1525 m_brush
.GetColour().CalcPixel( m_cmap
);
1526 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
1528 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
1530 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1532 if (m_brush
.GetStipple()->GetPixmap())
1534 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillTiled
);
1535 XSetTile( (Display
*) m_display
, (GC
) m_brushGC
, (Pixmap
) m_brush
.GetStipple()->GetPixmap() );
1539 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1540 XSetStipple( (Display
*) m_display
, (GC
) m_brushGC
, (Pixmap
) m_brush
.GetStipple()->GetBitmap() );
1544 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1546 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillOpaqueStippled
);
1547 XSetStipple( (Display
*) m_display
, (GC
) m_textGC
, (Pixmap
) m_brush
.GetStipple()->GetMask()->GetBitmap() );
1550 if (IS_HATCH(m_brush
.GetStyle()))
1552 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1553 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1554 XSetStipple( (Display
*) m_display
, (GC
) m_brushGC
, hatches
[num
] );
1558 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1560 /* CMB 21/7/98: Added SetBackground. Sets background brush
1561 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1563 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1565 if (m_backgroundBrush
== brush
) return;
1567 m_backgroundBrush
= brush
;
1569 if (!m_backgroundBrush
.Ok()) return;
1571 if (!m_window
) return;
1573 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1574 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, m_backgroundBrush
.GetColour().GetPixel() );
1575 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, m_backgroundBrush
.GetColour().GetPixel() );
1576 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1577 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1579 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
1581 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1583 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1585 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillTiled
);
1586 XSetTile( (Display
*) m_display
, (GC
) m_bgGC
, (Pixmap
) m_backgroundBrush
.GetStipple()->GetPixmap() );
1590 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1591 XSetStipple( (Display
*) m_display
, (GC
) m_bgGC
, (Pixmap
) m_backgroundBrush
.GetStipple()->GetBitmap() );
1595 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1597 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1598 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1599 XSetStipple( (Display
*) m_display
, (GC
) m_bgGC
, hatches
[num
] );
1603 void wxWindowDC::SetLogicalFunction( int function
)
1605 wxCHECK_RET( Ok(), "invalid dc" );
1609 if (m_logicalFunction
== function
)
1612 // VZ: shouldn't this be a CHECK?
1619 x_function
= GXclear
;
1625 x_function
= GXinvert
;
1628 x_function
= GXorReverse
;
1631 x_function
= GXandReverse
;
1640 x_function
= GXandInverted
;
1643 x_function
= GXnoop
;
1649 x_function
= GXequiv
;
1652 x_function
= GXcopyInverted
;
1655 x_function
= GXorInverted
;
1658 x_function
= GXnand
;
1665 x_function
= GXcopy
;
1669 XSetFunction( (Display
*) m_display
, (GC
) m_penGC
, x_function
);
1670 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, x_function
);
1672 // to stay compatible with wxMSW, we don't apply ROPs to the text
1673 // operations (i.e. DrawText/DrawRotatedText).
1674 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1675 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, x_function
);
1677 m_logicalFunction
= function
;
1680 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1682 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1684 // don't set m_textForegroundColour to an invalid colour as we'd crash
1685 // later then (we use m_textForegroundColour.GetColor() without checking
1687 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1690 m_textForegroundColour
= col
;
1694 m_textForegroundColour
.CalcPixel( m_cmap
);
1695 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
1699 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1701 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1704 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1707 m_textBackgroundColour
= col
;
1711 m_textBackgroundColour
.CalcPixel( m_cmap
);
1712 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
1716 void wxWindowDC::SetBackgroundMode( int mode
)
1718 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1720 m_backgroundMode
= mode
;
1723 GrSetGCUseBackground((GC
) m_textGC
, mode
== wxTRANSPARENT
? FALSE
: TRUE
);
1726 if (!m_window
) return;
1728 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1729 // transparent/solid background mode
1731 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1733 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
,
1734 (m_backgroundMode
== wxTRANSPARENT
) ? FillStippled
: FillOpaqueStippled
);
1738 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1744 /* Use GetXColormap */
1745 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1746 (Colormap
) palette
.GetXColormap());
1748 /* Use wxGetMainColormap */
1749 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1750 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1755 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1757 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1759 if (!m_window
) return;
1762 rect
.x
= XLOG2DEV(x
);
1763 rect
.y
= YLOG2DEV(y
);
1764 rect
.width
= XLOG2DEVREL(width
);
1765 rect
.height
= YLOG2DEVREL(height
);
1767 if (!m_currentClippingRegion
.IsNull())
1768 m_currentClippingRegion
.Intersect( rect
);
1770 m_currentClippingRegion
.Union( rect
);
1772 #if USE_PAINT_REGION
1773 if (!m_paintClippingRegion
.IsNull())
1774 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1777 wxCoord xx
, yy
, ww
, hh
;
1778 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1779 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1781 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1782 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1783 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1784 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1787 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
1789 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1793 DestroyClippingRegion();
1797 if (!m_window
) return;
1799 if (!m_currentClippingRegion
.IsNull())
1800 m_currentClippingRegion
.Intersect( region
);
1802 m_currentClippingRegion
.Union( region
);
1804 #if USE_PAINT_REGION
1805 if (!m_paintClippingRegion
.IsNull())
1806 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1809 wxCoord xx
, yy
, ww
, hh
;
1810 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1811 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1813 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1814 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1815 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1816 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1819 void wxWindowDC::DestroyClippingRegion()
1821 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1823 wxDC::DestroyClippingRegion();
1825 m_currentClippingRegion
.Clear();
1827 #if USE_PAINT_REGION
1828 if (!m_paintClippingRegion
.IsEmpty())
1829 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1832 if (!m_window
) return;
1834 if (m_currentClippingRegion
.IsEmpty())
1836 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
1837 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
1838 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
1839 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
1843 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1844 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1845 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1846 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1850 void wxWindowDC::Destroy()
1852 if (m_penGC
) wxFreePoolGC( (GC
) m_penGC
);
1854 if (m_brushGC
) wxFreePoolGC( (GC
) m_brushGC
);
1856 if (m_textGC
) wxFreePoolGC( (GC
) m_textGC
);
1858 if (m_bgGC
) wxFreePoolGC( (GC
) m_bgGC
);
1862 void wxWindowDC::ComputeScaleAndOrigin()
1864 /* CMB: copy scale to see if it changes */
1865 double origScaleX
= m_scaleX
;
1866 double origScaleY
= m_scaleY
;
1868 wxDC::ComputeScaleAndOrigin();
1870 /* CMB: if scale has changed call SetPen to recalulate the line width */
1871 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1874 /* this is a bit artificial, but we need to force wxDC to think
1875 the pen has changed */
1882 wxSize
wxWindowDC::GetPPI() const
1884 return wxSize(100, 100);
1887 int wxWindowDC::GetDepth() const
1889 wxFAIL_MSG(wxT("not implemented"));
1894 // ----------------------------------------------------------------------------
1896 // ----------------------------------------------------------------------------
1898 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
1900 wxPaintDC::wxPaintDC(wxWindow
* win
)
1903 #if USE_PAINT_REGION
1904 if (!win
->GetClipPaintRegion())
1907 m_paintClippingRegion
= win
->GetUpdateRegion();
1908 Region region
= (Region
) m_paintClippingRegion
.GetX11Region();
1911 m_paintClippingRegion
= win
->GetUpdateRegion();
1912 Region region2
= (Region
) m_paintClippingRegion
.GetX11Region();
1915 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1917 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, region2
);
1918 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, region2
);
1919 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, region2
);
1920 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, region2
);
1923 #endif // USE_PAINT_REGION
1926 //-----------------------------------------------------------------------------
1928 //-----------------------------------------------------------------------------
1930 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
1932 wxClientDC::wxClientDC( wxWindow
*win
)
1935 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
1937 #ifdef __WXUNIVERSAL__
1938 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
1939 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
1940 wxSize size
= win
->GetClientSize();
1941 SetClippingRegion(wxPoint(0, 0), size
);
1942 #endif // __WXUNIVERSAL__
1945 void wxClientDC::DoGetSize(int *width
, int *height
) const
1947 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
1949 m_owner
->GetClientSize( width
, height
);
1952 // ----------------------------------------------------------------------------
1954 // ----------------------------------------------------------------------------
1956 class wxDCModule
: public wxModule
1963 DECLARE_DYNAMIC_CLASS(wxDCModule
)
1966 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
1968 bool wxDCModule::OnInit()
1974 void wxDCModule::OnExit()