]>
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 m_pen
.GetColour().CalcPixel( m_cmap
);
260 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
261 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, bg_col
);
263 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, 0, LineSolid
, CapNotLast
, JoinRound
);
266 m_brush
.GetColour().CalcPixel( m_cmap
);
267 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
268 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, bg_col
);
270 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
273 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
274 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
276 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
279 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, GXcopy
);
280 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, GXcopy
);
281 XSetFunction( (Display
*) m_display
, (GC
)m_penGC
, GXcopy
);
284 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
285 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
286 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
287 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
291 int xscreen
= DefaultScreen( (Display
*) m_display
);
292 Window xroot
= RootWindow( (Display
*) m_display
, xscreen
);
294 hatch_bitmap
= hatches
;
295 hatch_bitmap
[0] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, bdiag_bits
, bdiag_width
, bdiag_height
);
296 hatch_bitmap
[1] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cdiag_bits
, cdiag_width
, cdiag_height
);
297 hatch_bitmap
[2] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, fdiag_bits
, fdiag_width
, fdiag_height
);
298 hatch_bitmap
[3] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cross_bits
, cross_width
, cross_height
);
299 hatch_bitmap
[4] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, horiz_bits
, horiz_width
, horiz_height
);
300 hatch_bitmap
[5] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, verti_bits
, verti_width
, verti_height
);
304 void wxWindowDC::DoGetSize( int* width
, int* height
) const
306 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
308 m_owner
->GetSize(width
, height
);
311 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
312 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
314 wxFAIL_MSG("not implemented");
317 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
319 // Generic (and therefore rather inefficient) method.
320 // Could be improved.
322 wxBitmap
bitmap(1, 1);
323 memdc
.SelectObject(bitmap
);
324 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
325 memdc
.SelectObject(wxNullBitmap
);
326 wxImage
image(bitmap
);
327 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
331 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
333 wxCHECK_RET( Ok(), wxT("invalid window dc") );
335 if (m_pen
.GetStyle() != wxTRANSPARENT
)
338 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
339 (GC
) m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
341 CalcBoundingBox(x1
, y1
);
342 CalcBoundingBox(x2
, y2
);
346 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
348 wxCHECK_RET( Ok(), wxT("invalid window dc") );
350 if (m_pen
.GetStyle() != wxTRANSPARENT
)
355 wxCoord xx
= XLOG2DEV(x
);
356 wxCoord yy
= YLOG2DEV(y
);
359 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
360 (GC
) m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
361 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
362 (GC
) m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
367 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
369 wxCHECK_RET( Ok(), wxT("invalid window dc") );
371 wxCoord xx1
= XLOG2DEV(x1
);
372 wxCoord yy1
= YLOG2DEV(y1
);
373 wxCoord xx2
= XLOG2DEV(x2
);
374 wxCoord yy2
= YLOG2DEV(y2
);
375 wxCoord xxc
= XLOG2DEV(xc
);
376 wxCoord yyc
= YLOG2DEV(yc
);
377 double dx
= xx1
- xxc
;
378 double dy
= yy1
- yyc
;
379 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
380 wxCoord r
= (wxCoord
)radius
;
381 double radius1
, radius2
;
383 if (xx1
== xx2
&& yy1
== yy2
)
391 radius1
= radius2
= 0.0;
395 radius1
= (xx1
- xxc
== 0) ?
396 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
397 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
398 radius2
= (xx2
- xxc
== 0) ?
399 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
400 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
402 wxCoord alpha1
= wxCoord(radius1
* 64.0);
403 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
404 while (alpha2
<= 0) alpha2
+= 360*64;
405 while (alpha1
> 360*64) alpha1
-= 360*64;
409 if (m_brush
.GetStyle() != wxTRANSPARENT
)
411 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
413 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
414 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
415 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
417 XFillArc( (Display
*) m_display
, (Window
) m_window
,
418 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
420 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
422 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
424 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
425 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
427 XFillArc( (Display
*) m_display
, (Window
) m_window
,
428 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
430 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
432 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
434 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
435 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
437 XFillArc( (Display
*) m_display
, (Window
) m_window
,
438 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
440 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
442 if (m_brush
.GetStyle() == wxSTIPPLE
)
444 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
445 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
446 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
448 XFillArc( (Display
*) m_display
, (Window
) m_window
,
449 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
451 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
455 XFillArc( (Display
*) m_display
, (Window
) m_window
,
456 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
460 if (m_pen
.GetStyle() != wxTRANSPARENT
)
462 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
463 (GC
) m_penGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
465 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
466 (GC
) m_penGC
, xx1
, yy1
, xxc
, yyc
);
468 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
469 (GC
) m_penGC
, xxc
, yyc
, xx2
, yy2
);
473 CalcBoundingBox (x1
, y1
);
474 CalcBoundingBox (x2
, y2
);
477 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
479 wxCHECK_RET( Ok(), wxT("invalid window dc") );
481 wxCoord xx
= XLOG2DEV(x
);
482 wxCoord yy
= YLOG2DEV(y
);
483 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
484 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
486 // CMB: handle -ve width and/or height
487 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
488 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
492 wxCoord start
= wxCoord(sa
* 64.0);
493 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
495 if (m_brush
.GetStyle() != wxTRANSPARENT
)
497 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
499 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
500 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
501 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
503 XFillArc( (Display
*) m_display
, (Window
) m_window
,
504 (GC
) m_textGC
, xx
, yy
, ww
, hh
, start
, end
);
506 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
508 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
510 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
511 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
513 XFillArc( (Display
*) m_display
, (Window
) m_window
,
514 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
516 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
518 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
520 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
521 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
523 XFillArc( (Display
*) m_display
, (Window
) m_window
,
524 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
526 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
528 if (m_brush
.GetStyle() == wxSTIPPLE
)
530 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
531 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
532 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
534 XFillArc( (Display
*) m_display
, (Window
) m_window
,
535 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
537 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
541 XFillArc( (Display
*) m_display
, (Window
) m_window
,
542 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
546 if (m_pen
.GetStyle() != wxTRANSPARENT
)
548 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
549 (GC
) m_penGC
, xx
, yy
, ww
, hh
, start
, end
);
553 CalcBoundingBox (x
, y
);
554 CalcBoundingBox (x
+ width
, y
+ height
);
557 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
559 wxCHECK_RET( Ok(), wxT("invalid window dc") );
561 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
562 XDrawPoint( (Display
*) m_display
, (Window
) m_window
,
563 (GC
) m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
565 CalcBoundingBox (x
, y
);
568 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
570 wxCHECK_RET( Ok(), wxT("invalid window dc") );
572 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
575 XPoint
*xpoints
= new XPoint
[n
];
576 for (int i
= 0; i
< n
; i
++)
578 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
579 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
581 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
583 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
, 0 );
588 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
589 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
591 wxCHECK_RET( Ok(), wxT("invalid window dc") );
595 XPoint
*xpoints
= new XPoint
[n
+ 1];
597 for (i
= 0; i
< n
; i
++)
599 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
600 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
602 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
607 if (m_brush
.GetStyle() != wxTRANSPARENT
)
610 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
612 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
613 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
614 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
616 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
617 (GC
) m_textGC
, xpoints
, n
, Complex
, 0);
619 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
621 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
623 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
624 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
626 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
627 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
629 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
631 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
633 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
634 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
636 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
637 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
639 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
641 if (m_brush
.GetStyle() == wxSTIPPLE
)
643 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
644 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
645 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
647 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
648 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
650 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
654 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
655 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
659 if (m_pen
.GetStyle () != wxTRANSPARENT
)
661 // Close figure for XDrawLines
662 xpoints
[i
].x
= xpoints
[0].x
;
663 xpoints
[i
].y
= xpoints
[0].y
;
665 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
+ 1, 0);
672 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
674 wxCHECK_RET( Ok(), wxT("invalid window dc") );
676 wxCoord xx
= XLOG2DEV(x
);
677 wxCoord yy
= YLOG2DEV(y
);
678 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
679 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
681 // CMB: draw nothing if transformed w or h is 0
682 if (ww
== 0 || hh
== 0) return;
684 // CMB: handle -ve width and/or height
685 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
686 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
690 if (m_brush
.GetStyle() != wxTRANSPARENT
)
692 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
694 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
695 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
696 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
698 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
699 (GC
) m_textGC
, xx
, yy
, ww
, hh
);
701 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
703 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
705 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
706 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
708 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
709 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
711 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
713 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
715 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
716 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
718 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
719 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
721 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
723 if (m_brush
.GetStyle() == wxSTIPPLE
)
725 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
726 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
727 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
729 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
730 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
732 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
736 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
737 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
741 if (m_pen
.GetStyle () != wxTRANSPARENT
)
743 XDrawRectangle( (Display
*) m_display
, (Window
) m_window
,
744 (GC
) m_penGC
, xx
, yy
, ww
-1, hh
-1 );
748 CalcBoundingBox( x
, y
);
749 CalcBoundingBox( x
+ width
, y
+ height
);
752 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
757 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
759 wxCHECK_RET( Ok(), wxT("invalid window dc") );
761 wxCoord xx
= XLOG2DEV(x
);
762 wxCoord yy
= YLOG2DEV(y
);
763 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
764 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
766 // CMB: handle -ve width and/or height
767 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
768 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
772 if (m_brush
.GetStyle() != wxTRANSPARENT
)
774 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
776 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
777 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
778 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
780 XFillArc( (Display
*) m_display
, (Window
) m_window
,
781 (GC
) m_textGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
783 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
785 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
787 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
788 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
790 XFillArc( (Display
*) m_display
, (Window
) m_window
,
791 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
793 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
795 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
797 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
798 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
800 XFillArc( (Display
*) m_display
, (Window
) m_window
,
801 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
803 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
805 if (m_brush
.GetStyle() == wxSTIPPLE
)
807 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
808 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
809 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
811 XFillArc( (Display
*) m_display
, (Window
) m_window
,
812 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
814 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
818 XFillArc( (Display
*) m_display
, (Window
) m_window
,
819 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
823 if (m_pen
.GetStyle () != wxTRANSPARENT
)
825 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
826 (GC
) m_penGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
830 CalcBoundingBox( x
, y
);
831 CalcBoundingBox( x
+ width
, y
+ height
);
834 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
838 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
839 wxCoord x
, wxCoord y
,
842 wxCHECK_RET( Ok(), wxT("invalid window dc") );
844 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
846 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
848 /* scale/translate size and position */
849 int xx
= XLOG2DEV(x
);
850 int yy
= YLOG2DEV(y
);
852 int w
= bitmap
.GetWidth();
853 int h
= bitmap
.GetHeight();
855 CalcBoundingBox( x
, y
);
856 CalcBoundingBox( x
+ w
, y
+ h
);
858 if (!m_window
) return;
860 int ww
= XLOG2DEVREL(w
);
861 int hh
= YLOG2DEVREL(h
);
863 /* compare to current clipping region */
864 if (!m_currentClippingRegion
.IsNull())
866 wxRegion
tmp( xx
,yy
,ww
,hh
);
867 tmp
.Intersect( m_currentClippingRegion
);
872 /* scale bitmap if required */
874 if ((w
!= ww
) || (h
!= hh
))
876 wxImage
image( bitmap
);
877 image
.Rescale( ww
, hh
);
880 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
883 use_bitmap
= image
.ConvertToBitmap();
890 /* apply mask if any */
891 WXPixmap mask
= NULL
;
892 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
896 WXPixmap new_mask
= NULL
;
898 if (!m_currentClippingRegion
.IsNull())
901 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
902 GdkGC
*gc
= gdk_gc_new( new_mask
);
904 gdk_gc_set_foreground( gc
, &col
);
905 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
907 gdk_gc_set_background( gc
, &col
);
909 gdk_gc_set_foreground( gc
, &col
);
910 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
911 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
912 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
913 gdk_gc_set_stipple( gc
, mask
);
914 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
921 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, (Pixmap
) new_mask
);
923 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, (Pixmap
) mask
);
924 XSetClipOrigin( (Display
*) m_display
, (GC
) m_textGC
, xx
, yy
);
929 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, (Pixmap
) new_mask
);
931 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, (Pixmap
) mask
);
932 XSetClipOrigin( (Display
*) m_display
, (GC
) m_penGC
, xx
, yy
);
936 XFreePixmap( (Display
*) m_display
, (Pixmap
) new_mask
);
940 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
941 drawing a mono-bitmap (XBitmap) we use the current text GC */
943 XCopyPlane( (Display
*) m_display
, (Pixmap
) use_bitmap
.GetBitmap(), (Window
) m_window
,
944 (GC
) m_textGC
, 0, 0, w
, h
, xx
, yy
, 1 );
946 XCopyArea( (Display
*) m_display
, (Pixmap
) use_bitmap
.GetPixmap(), (Window
) m_window
,
947 (GC
) m_penGC
, 0, 0, w
, h
, xx
, yy
);
949 /* remove mask again if any */
954 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
955 XSetClipOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
956 if (!m_currentClippingRegion
.IsNull())
957 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
961 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
962 XSetClipOrigin( (Display
*) m_display
, (GC
) m_penGC
, 0, 0 );
963 if (!m_currentClippingRegion
.IsNull())
964 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
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") );
1236 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1237 wxCoord height
= font
->ascent
+ font
->descent
;
1239 if ( m_backgroundMode
== wxSOLID
)
1241 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1242 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1243 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1247 XSetFont( (Display
*) m_display
, (GC
) m_textGC
, xfont
->fid
);
1249 if ((xfont
->min_byte1
== 0) && (xfont
->max_byte1
== 0))
1252 XDrawString( (Display
*) m_display
, (Window
) m_window
,
1253 (GC
) m_textGC
, x
, y
+ XFontStructGetAscent(xfont
), text
.c_str(), text
.Len() );
1257 if (m_font
.GetUnderlined())
1259 wxCoord ul_y
= y
+ XFontStructGetAscent(font
);
1260 if (font
->descent
> 0) ul_y
++;
1261 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1264 width
= wxCoord(width
/ m_scaleX
);
1265 height
= wxCoord(height
/ m_scaleY
);
1267 CalcBoundingBox (x
+ width
, y
+ height
);
1268 CalcBoundingBox (x
, y
);
1272 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1277 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1278 wxCoord
*descent
, wxCoord
*externalLeading
,
1279 wxFont
*font
) const
1281 wxCHECK_RET( Ok(), "invalid dc" );
1283 wxFont fontToUse
= m_font
;
1284 if (font
) fontToUse
= *font
;
1286 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
1288 XFontStruct
*xfont
= (XFontStruct
*) fontToUse
.GetFontStruct( m_scaleY
, m_display
);
1290 wxCHECK_RET( xfont
, wxT("invalid font") );
1292 int direction
, ascent
, descent2
;
1293 XCharStruct overall
;
1295 XTextExtents( xfont
, (char*) string
.c_str(), string
.Len(), &direction
,
1296 &ascent
, &descent2
, &overall
);
1299 *width
= (wxCoord
)( overall
.width
/ m_scaleX
);
1301 *height
= (wxCoord
)((ascent
+ descent2
) / m_scaleY
);
1303 *descent
= (wxCoord
)(descent2
/ m_scaleY
);
1304 if (externalLeading
)
1305 *externalLeading
= 0; // ??
1308 wxCoord
wxWindowDC::GetCharWidth() const
1310 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1312 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1314 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1316 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1318 int direction
, ascent
, descent
;
1319 XCharStruct overall
;
1321 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1323 return (wxCoord
)(overall
.width
/ m_scaleX
);
1326 wxCoord
wxWindowDC::GetCharHeight() const
1328 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1330 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1332 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1334 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1336 int direction
, ascent
, descent
;
1337 XCharStruct overall
;
1339 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1341 return (wxCoord
)((ascent
+descent
) / m_scaleY
);
1344 void wxWindowDC::Clear()
1346 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1348 if (!m_window
) return;
1350 /* - we either are a memory dc or have a window as the
1351 owner. anything else shouldn't happen.
1352 - we don't use gdk_window_clear() as we don't set
1353 the window's background colour anymore. it is too
1354 much pain to keep the DC's and the window's back-
1355 ground colour in synch. */
1360 m_owner
->GetSize( &width
, &height
);
1361 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1368 GetSize( &width
, &height
);
1369 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1374 void wxWindowDC::SetFont( const wxFont
&font
)
1376 wxCHECK_RET( Ok(), "invalid dc" );
1381 void wxWindowDC::SetPen( const wxPen
&pen
)
1383 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1385 if (m_pen
== pen
) return;
1389 if (!m_pen
.Ok()) return;
1391 if (!m_window
) return;
1393 int width
= m_pen
.GetWidth();
1396 // CMB: if width is non-zero scale it with the dc
1401 // X doesn't allow different width in x and y and so we take
1404 ( fabs((double) XLOG2DEVREL(width
)) +
1405 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1409 static const wxX11Dash dotted
[] = {1, 1};
1410 static const wxX11Dash short_dashed
[] = {2, 2};
1411 static const wxX11Dash long_dashed
[] = {2, 4};
1412 static const wxX11Dash dotted_dashed
[] = {3, 3, 1, 3};
1414 // We express dash pattern in pen width unit, so we are
1415 // independent of zoom factor and so on...
1417 const wxX11Dash
*req_dash
;
1419 int lineStyle
= LineSolid
;
1420 switch (m_pen
.GetStyle())
1424 lineStyle
= LineOnOffDash
;
1425 req_nb_dash
= m_pen
.GetDashCount();
1426 req_dash
= (wxX11Dash
*)m_pen
.GetDash();
1431 lineStyle
= LineOnOffDash
;
1438 lineStyle
= LineOnOffDash
;
1440 req_dash
= long_dashed
;
1445 lineStyle
= LineOnOffDash
;
1447 req_dash
= short_dashed
;
1452 // lineStyle = LineDoubleDash;
1453 lineStyle
= LineOnOffDash
;
1455 req_dash
= dotted_dashed
;
1460 case wxSTIPPLE_MASK_OPAQUE
:
1465 lineStyle
= LineSolid
;
1466 req_dash
= (wxX11Dash
*)NULL
;
1472 int capStyle
= CapRound
;
1473 switch (m_pen
.GetCap())
1475 case wxCAP_PROJECTING
: { capStyle
= CapProjecting
; break; }
1476 case wxCAP_BUTT
: { capStyle
= CapButt
; break; }
1483 capStyle
= CapNotLast
;
1487 capStyle
= CapRound
;
1493 int joinStyle
= JoinRound
;
1494 switch (m_pen
.GetJoin())
1496 case wxJOIN_BEVEL
: { joinStyle
= JoinBevel
; break; }
1497 case wxJOIN_MITER
: { joinStyle
= JoinMiter
; break; }
1499 default: { joinStyle
= JoinRound
; break; }
1502 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1504 m_pen
.GetColour().CalcPixel( m_cmap
);
1505 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
1508 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1510 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1512 if (m_brush
== brush
) return;
1516 if (!m_brush
.Ok()) return;
1518 if (!m_window
) return;
1520 m_brush
.GetColour().CalcPixel( m_cmap
);
1521 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
1523 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
1525 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1527 if (m_brush
.GetStipple()->GetPixmap())
1529 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillTiled
);
1530 XSetTile( (Display
*) m_display
, (GC
) m_brushGC
, (Pixmap
) m_brush
.GetStipple()->GetPixmap() );
1534 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1535 XSetStipple( (Display
*) m_display
, (GC
) m_brushGC
, (Pixmap
) m_brush
.GetStipple()->GetBitmap() );
1539 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1541 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillOpaqueStippled
);
1542 XSetStipple( (Display
*) m_display
, (GC
) m_textGC
, (Pixmap
) m_brush
.GetStipple()->GetMask()->GetBitmap() );
1545 if (IS_HATCH(m_brush
.GetStyle()))
1547 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1548 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1549 XSetStipple( (Display
*) m_display
, (GC
) m_brushGC
, hatches
[num
] );
1553 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1555 /* CMB 21/7/98: Added SetBackground. Sets background brush
1556 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1558 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1560 if (m_backgroundBrush
== brush
) return;
1562 m_backgroundBrush
= brush
;
1564 if (!m_backgroundBrush
.Ok()) return;
1566 if (!m_window
) return;
1568 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1569 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, m_backgroundBrush
.GetColour().GetPixel() );
1570 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, m_backgroundBrush
.GetColour().GetPixel() );
1571 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1572 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1574 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
1576 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1578 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1580 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillTiled
);
1581 XSetTile( (Display
*) m_display
, (GC
) m_bgGC
, (Pixmap
) m_backgroundBrush
.GetStipple()->GetPixmap() );
1585 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1586 XSetStipple( (Display
*) m_display
, (GC
) m_bgGC
, (Pixmap
) m_backgroundBrush
.GetStipple()->GetBitmap() );
1590 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1592 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1593 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1594 XSetStipple( (Display
*) m_display
, (GC
) m_bgGC
, hatches
[num
] );
1598 void wxWindowDC::SetLogicalFunction( int function
)
1600 wxCHECK_RET( Ok(), "invalid dc" );
1604 if (m_logicalFunction
== function
)
1607 // VZ: shouldn't this be a CHECK?
1614 x_function
= GXclear
;
1620 x_function
= GXinvert
;
1623 x_function
= GXorReverse
;
1626 x_function
= GXandReverse
;
1635 x_function
= GXandInverted
;
1638 x_function
= GXnoop
;
1644 x_function
= GXequiv
;
1647 x_function
= GXcopyInverted
;
1650 x_function
= GXorInverted
;
1653 x_function
= GXnand
;
1660 x_function
= GXcopy
;
1664 XSetFunction( (Display
*) m_display
, (GC
) m_penGC
, x_function
);
1665 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, x_function
);
1667 // to stay compatible with wxMSW, we don't apply ROPs to the text
1668 // operations (i.e. DrawText/DrawRotatedText).
1669 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1670 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, x_function
);
1672 m_logicalFunction
= function
;
1675 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1677 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1679 // don't set m_textForegroundColour to an invalid colour as we'd crash
1680 // later then (we use m_textForegroundColour.GetColor() without checking
1682 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1685 m_textForegroundColour
= col
;
1689 m_textForegroundColour
.CalcPixel( m_cmap
);
1690 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
1694 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1696 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1699 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1702 m_textBackgroundColour
= col
;
1706 m_textBackgroundColour
.CalcPixel( m_cmap
);
1707 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
1711 void wxWindowDC::SetBackgroundMode( int mode
)
1713 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1715 m_backgroundMode
= mode
;
1717 if (!m_window
) return;
1719 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1720 // transparent/solid background mode
1722 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1724 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
,
1725 (m_backgroundMode
== wxTRANSPARENT
) ? FillStippled
: FillOpaqueStippled
);
1729 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1735 /* Use GetXColormap */
1736 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1737 (Colormap
) palette
.GetXColormap());
1739 /* Use wxGetMainColormap */
1740 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1741 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1746 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1748 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1750 if (!m_window
) return;
1753 rect
.x
= XLOG2DEV(x
);
1754 rect
.y
= YLOG2DEV(y
);
1755 rect
.width
= XLOG2DEVREL(width
);
1756 rect
.height
= YLOG2DEVREL(height
);
1758 if (!m_currentClippingRegion
.IsNull())
1759 m_currentClippingRegion
.Intersect( rect
);
1761 m_currentClippingRegion
.Union( rect
);
1763 #if USE_PAINT_REGION
1764 if (!m_paintClippingRegion
.IsNull())
1765 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1768 wxCoord xx
, yy
, ww
, hh
;
1769 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1770 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1772 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1773 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1774 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1775 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1778 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
1780 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1784 DestroyClippingRegion();
1788 if (!m_window
) return;
1790 if (!m_currentClippingRegion
.IsNull())
1791 m_currentClippingRegion
.Intersect( region
);
1793 m_currentClippingRegion
.Union( region
);
1795 #if USE_PAINT_REGION
1796 if (!m_paintClippingRegion
.IsNull())
1797 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1800 wxCoord xx
, yy
, ww
, hh
;
1801 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1802 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1804 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1805 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1806 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1807 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1810 void wxWindowDC::DestroyClippingRegion()
1812 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1814 wxDC::DestroyClippingRegion();
1816 m_currentClippingRegion
.Clear();
1818 #if USE_PAINT_REGION
1819 if (!m_paintClippingRegion
.IsEmpty())
1820 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1823 if (!m_window
) return;
1825 if (m_currentClippingRegion
.IsEmpty())
1827 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
1828 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
1829 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
1830 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
1834 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1835 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1836 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1837 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1841 void wxWindowDC::Destroy()
1843 if (m_penGC
) wxFreePoolGC( (GC
) m_penGC
);
1845 if (m_brushGC
) wxFreePoolGC( (GC
) m_brushGC
);
1847 if (m_textGC
) wxFreePoolGC( (GC
) m_textGC
);
1849 if (m_bgGC
) wxFreePoolGC( (GC
) m_bgGC
);
1853 void wxWindowDC::ComputeScaleAndOrigin()
1855 /* CMB: copy scale to see if it changes */
1856 double origScaleX
= m_scaleX
;
1857 double origScaleY
= m_scaleY
;
1859 wxDC::ComputeScaleAndOrigin();
1861 /* CMB: if scale has changed call SetPen to recalulate the line width */
1862 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1865 /* this is a bit artificial, but we need to force wxDC to think
1866 the pen has changed */
1873 wxSize
wxWindowDC::GetPPI() const
1875 return wxSize(100, 100);
1878 int wxWindowDC::GetDepth() const
1880 wxFAIL_MSG(wxT("not implemented"));
1885 // ----------------------------------------------------------------------------
1887 // ----------------------------------------------------------------------------
1889 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
1891 wxPaintDC::wxPaintDC(wxWindow
* win
)
1894 #if USE_PAINT_REGION
1895 if (!win
->GetClipPaintRegion())
1898 m_paintClippingRegion
= win
->GetUpdateRegion();
1899 Region region
= (Region
) m_paintClippingRegion
.GetX11Region();
1902 m_paintClippingRegion
= win
->GetUpdateRegion();
1903 Region region2
= (Region
) m_paintClippingRegion
.GetX11Region();
1906 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1908 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, region2
);
1909 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, region2
);
1910 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, region2
);
1911 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, region2
);
1914 #endif // USE_PAINT_REGION
1917 //-----------------------------------------------------------------------------
1919 //-----------------------------------------------------------------------------
1921 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
1923 wxClientDC::wxClientDC( wxWindow
*win
)
1926 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
1928 #ifdef __WXUNIVERSAL__
1929 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
1930 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
1931 wxSize size
= win
->GetClientSize();
1932 SetClippingRegion(wxPoint(0, 0), size
);
1933 #endif // __WXUNIVERSAL__
1936 void wxClientDC::DoGetSize(int *width
, int *height
) const
1938 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
1940 m_owner
->GetClientSize( width
, height
);
1943 // ----------------------------------------------------------------------------
1945 // ----------------------------------------------------------------------------
1947 class wxDCModule
: public wxModule
1954 DECLARE_DYNAMIC_CLASS(wxDCModule
)
1957 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
1959 bool wxDCModule::OnInit()
1965 void wxDCModule::OnExit()