]>
git.saurik.com Git - wxWidgets.git/blob - src/x11/dcclient.cpp
c00bb29e357c26182a34e1fbf6a9c0e8a37c69c0
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: Julian Smart, Robert Roebling
8 // Copyright: (c) Julian Smart, Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dcclient.h"
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
18 #include "wx/window.h"
22 #include "wx/x11/private.h"
26 //-----------------------------------------------------------------------------
28 //-----------------------------------------------------------------------------
30 #define USE_PAINT_REGION 1
32 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
44 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
45 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
47 static Pixmap hatches
[num_hatches
];
48 static Pixmap
*hatch_bitmap
= (Pixmap
*) NULL
;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
54 const double RAD2DEG
= 180.0 / M_PI
;
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
61 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
63 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
65 //-----------------------------------------------------------------------------
66 // Implement Pool of Graphic contexts. Creating them takes too much time.
67 //-----------------------------------------------------------------------------
69 #define GC_POOL_SIZE 200
95 static wxGC wxGCPool
[GC_POOL_SIZE
];
97 static void wxInitGCPool()
99 memset( wxGCPool
, 0, GC_POOL_SIZE
*sizeof(wxGC
) );
102 static void wxCleanUpGCPool()
104 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
106 if (wxGCPool
[i
].m_gc
)
107 XFreeGC( wxGlobalDisplay(), wxGCPool
[i
].m_gc
);
111 static GC
wxGetPoolGC( Window window
, wxPoolGCType type
)
113 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
115 if (!wxGCPool
[i
].m_gc
)
117 wxGCPool
[i
].m_gc
= XCreateGC( wxGlobalDisplay(), window
, 0, NULL
);
118 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool
[i
].m_gc
, FALSE
);
119 wxGCPool
[i
].m_type
= type
;
120 wxGCPool
[i
].m_used
= FALSE
;
122 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
124 wxGCPool
[i
].m_used
= TRUE
;
125 return wxGCPool
[i
].m_gc
;
129 wxFAIL_MSG( wxT("No GC available") );
134 static void wxFreePoolGC( GC gc
)
136 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
138 if (wxGCPool
[i
].m_gc
== gc
)
140 wxGCPool
[i
].m_used
= FALSE
;
145 wxFAIL_MSG( wxT("Wrong GC") );
148 // ----------------------------------------------------------------------------
150 // ----------------------------------------------------------------------------
152 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
154 wxWindowDC::wxWindowDC()
156 m_display
= (WXDisplay
*) NULL
;
157 m_penGC
= (WXGC
*) NULL
;
158 m_brushGC
= (WXGC
*) NULL
;
159 m_textGC
= (WXGC
*) NULL
;
160 m_bgGC
= (WXGC
*) NULL
;
161 m_cmap
= (WXColormap
*) NULL
;
163 m_isScreenDC
= FALSE
;
164 m_owner
= (wxWindow
*)NULL
;
167 wxWindowDC::wxWindowDC( wxWindow
*window
)
169 wxASSERT_MSG( window
, wxT("DC needs a window") );
171 m_display
= (WXDisplay
*) NULL
;
172 m_penGC
= (WXGC
*) NULL
;
173 m_brushGC
= (WXGC
*) NULL
;
174 m_textGC
= (WXGC
*) NULL
;
175 m_bgGC
= (WXGC
*) NULL
;
176 m_cmap
= (WXColormap
*) NULL
;
177 m_owner
= (wxWindow
*)NULL
;
179 m_isScreenDC
= FALSE
;
180 m_font
= window
->GetFont();
182 m_window
= (WXWindow
*) window
->GetMainWindow();
187 // don't report problems
193 m_display
= (WXDisplay
*) wxGlobalDisplay();
195 int screen
= DefaultScreen( (Display
*) m_display
);
196 m_cmap
= (WXColormap
) DefaultColormap( (Display
*) m_display
, screen
);
200 /* this must be done after SetUpDC, bacause SetUpDC calls the
201 repective SetBrush, SetPen, SetBackground etc functions
202 to set up the DC. SetBackground call m_owner->SetBackground
203 and this might not be desired as the standard dc background
204 is white whereas a window might assume gray to be the
205 standard (as e.g. wxStatusBar) */
210 wxWindowDC::~wxWindowDC()
215 void wxWindowDC::SetUpDC()
219 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
223 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_SCREEN
);
224 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_SCREEN
);
225 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_SCREEN
);
226 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_SCREEN
);
230 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
232 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_MONO
);
233 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_MONO
);
234 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_MONO
);
235 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_MONO
);
240 m_penGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxPEN_COLOUR
);
241 m_brushGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBRUSH_COLOUR
);
242 m_textGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxTEXT_COLOUR
);
243 m_bgGC
= (WXGC
*) wxGetPoolGC( (Window
) m_window
, wxBG_COLOUR
);
246 /* background colour */
247 m_backgroundBrush
= *wxWHITE_BRUSH
;
248 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
249 unsigned long bg_col
= m_backgroundBrush
.GetColour().GetPixel();
252 m_textForegroundColour
.CalcPixel( m_cmap
);
253 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
255 m_textBackgroundColour
.CalcPixel( m_cmap
);
256 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
258 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillSolid
);
261 m_pen
.GetColour().CalcPixel( m_cmap
);
262 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
263 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, bg_col
);
265 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, 0, LineSolid
, CapNotLast
, JoinRound
);
268 m_brush
.GetColour().CalcPixel( m_cmap
);
269 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
270 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, bg_col
);
272 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
275 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
276 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, bg_col
);
278 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
281 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, GXcopy
);
282 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, GXcopy
);
283 XSetFunction( (Display
*) m_display
, (GC
)m_penGC
, GXcopy
);
286 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
287 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
288 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
289 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
293 int xscreen
= DefaultScreen( (Display
*) m_display
);
294 Window xroot
= RootWindow( (Display
*) m_display
, xscreen
);
296 hatch_bitmap
= hatches
;
297 hatch_bitmap
[0] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, bdiag_bits
, bdiag_width
, bdiag_height
);
298 hatch_bitmap
[1] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cdiag_bits
, cdiag_width
, cdiag_height
);
299 hatch_bitmap
[2] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, fdiag_bits
, fdiag_width
, fdiag_height
);
300 hatch_bitmap
[3] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, cross_bits
, cross_width
, cross_height
);
301 hatch_bitmap
[4] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, horiz_bits
, horiz_width
, horiz_height
);
302 hatch_bitmap
[5] = XCreateBitmapFromData( (Display
*) m_display
, xroot
, verti_bits
, verti_width
, verti_height
);
306 void wxWindowDC::DoGetSize( int* width
, int* height
) const
308 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
310 m_owner
->GetSize(width
, height
);
313 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
),
314 const wxColour
& WXUNUSED(col
), int WXUNUSED(style
) )
316 wxFAIL_MSG("not implemented");
319 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
321 // Generic (and therefore rather inefficient) method.
322 // Could be improved.
324 wxBitmap
bitmap(1, 1);
325 memdc
.SelectObject(bitmap
);
326 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
327 memdc
.SelectObject(wxNullBitmap
);
328 wxImage
image(bitmap
);
329 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
333 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
335 wxCHECK_RET( Ok(), wxT("invalid window dc") );
337 if (m_pen
.GetStyle() != wxTRANSPARENT
)
340 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
341 (GC
) m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
343 CalcBoundingBox(x1
, y1
);
344 CalcBoundingBox(x2
, y2
);
346 wxLogDebug("Drawing line at %d, %d -> %d, %d", XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
350 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
352 wxCHECK_RET( Ok(), wxT("invalid window dc") );
354 if (m_pen
.GetStyle() != wxTRANSPARENT
)
359 wxCoord xx
= XLOG2DEV(x
);
360 wxCoord yy
= YLOG2DEV(y
);
363 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
364 (GC
) m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
365 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
366 (GC
) m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
371 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
373 wxCHECK_RET( Ok(), wxT("invalid window dc") );
375 wxCoord xx1
= XLOG2DEV(x1
);
376 wxCoord yy1
= YLOG2DEV(y1
);
377 wxCoord xx2
= XLOG2DEV(x2
);
378 wxCoord yy2
= YLOG2DEV(y2
);
379 wxCoord xxc
= XLOG2DEV(xc
);
380 wxCoord yyc
= YLOG2DEV(yc
);
381 double dx
= xx1
- xxc
;
382 double dy
= yy1
- yyc
;
383 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
384 wxCoord r
= (wxCoord
)radius
;
385 double radius1
, radius2
;
387 if (xx1
== xx2
&& yy1
== yy2
)
395 radius1
= radius2
= 0.0;
399 radius1
= (xx1
- xxc
== 0) ?
400 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
401 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
402 radius2
= (xx2
- xxc
== 0) ?
403 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
404 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
406 wxCoord alpha1
= wxCoord(radius1
* 64.0);
407 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
408 while (alpha2
<= 0) alpha2
+= 360*64;
409 while (alpha1
> 360*64) alpha1
-= 360*64;
413 if (m_brush
.GetStyle() != wxTRANSPARENT
)
415 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
417 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
418 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
419 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
421 XFillArc( (Display
*) m_display
, (Window
) m_window
,
422 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
424 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
426 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
428 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
429 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
431 XFillArc( (Display
*) m_display
, (Window
) m_window
,
432 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
434 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
436 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
438 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
439 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
441 XFillArc( (Display
*) m_display
, (Window
) m_window
,
442 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
444 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
446 if (m_brush
.GetStyle() == wxSTIPPLE
)
448 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
449 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
450 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
452 XFillArc( (Display
*) m_display
, (Window
) m_window
,
453 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
455 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
459 XFillArc( (Display
*) m_display
, (Window
) m_window
,
460 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
464 if (m_pen
.GetStyle() != wxTRANSPARENT
)
466 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
467 (GC
) m_penGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
469 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
470 (GC
) m_penGC
, xx1
, yy1
, xxc
, yyc
);
472 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
473 (GC
) m_penGC
, xxc
, yyc
, xx2
, yy2
);
477 CalcBoundingBox (x1
, y1
);
478 CalcBoundingBox (x2
, y2
);
481 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
483 wxCHECK_RET( Ok(), wxT("invalid window dc") );
485 wxCoord xx
= XLOG2DEV(x
);
486 wxCoord yy
= YLOG2DEV(y
);
487 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
488 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
490 // CMB: handle -ve width and/or height
491 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
492 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
496 wxCoord start
= wxCoord(sa
* 64.0);
497 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
499 if (m_brush
.GetStyle() != wxTRANSPARENT
)
501 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
503 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
504 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
505 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
507 XFillArc( (Display
*) m_display
, (Window
) m_window
,
508 (GC
) m_textGC
, xx
, yy
, ww
, hh
, start
, end
);
510 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
512 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
514 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
515 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
517 XFillArc( (Display
*) m_display
, (Window
) m_window
,
518 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
520 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
522 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
524 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
525 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
527 XFillArc( (Display
*) m_display
, (Window
) m_window
,
528 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
530 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
532 if (m_brush
.GetStyle() == wxSTIPPLE
)
534 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
535 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
536 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
538 XFillArc( (Display
*) m_display
, (Window
) m_window
,
539 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
541 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
545 XFillArc( (Display
*) m_display
, (Window
) m_window
,
546 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
550 if (m_pen
.GetStyle() != wxTRANSPARENT
)
552 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
553 (GC
) m_penGC
, xx
, yy
, ww
, hh
, start
, end
);
557 CalcBoundingBox (x
, y
);
558 CalcBoundingBox (x
+ width
, y
+ height
);
561 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
563 wxCHECK_RET( Ok(), wxT("invalid window dc") );
565 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
566 XDrawPoint( (Display
*) m_display
, (Window
) m_window
,
567 (GC
) m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
569 CalcBoundingBox (x
, y
);
572 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
574 wxCHECK_RET( Ok(), wxT("invalid window dc") );
576 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
579 XPoint
*xpoints
= new XPoint
[n
];
580 for (int i
= 0; i
< n
; i
++)
582 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
583 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
585 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
587 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
, 0 );
592 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
593 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
595 wxCHECK_RET( Ok(), wxT("invalid window dc") );
599 XPoint
*xpoints
= new XPoint
[n
+ 1];
601 for (i
= 0; i
< n
; i
++)
603 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
604 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
606 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
611 if (m_brush
.GetStyle() != wxTRANSPARENT
)
614 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
616 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
617 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
618 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
620 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
621 (GC
) m_textGC
, xpoints
, n
, Complex
, 0);
623 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
625 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
627 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
628 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
630 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
631 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
633 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
635 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
637 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
638 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
640 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
641 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
643 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
645 if (m_brush
.GetStyle() == wxSTIPPLE
)
647 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
648 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
649 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
651 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
652 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
654 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
658 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
659 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
663 if (m_pen
.GetStyle () != wxTRANSPARENT
)
665 // Close figure for XDrawLines
666 xpoints
[i
].x
= xpoints
[0].x
;
667 xpoints
[i
].y
= xpoints
[0].y
;
669 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
+ 1, 0);
676 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
678 wxCHECK_RET( Ok(), wxT("invalid window dc") );
680 wxCoord xx
= XLOG2DEV(x
);
681 wxCoord yy
= YLOG2DEV(y
);
682 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
683 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
685 // CMB: draw nothing if transformed w or h is 0
686 if (ww
== 0 || hh
== 0) return;
688 // CMB: handle -ve width and/or height
689 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
690 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
694 if (m_brush
.GetStyle() != wxTRANSPARENT
)
696 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
698 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
699 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
700 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
702 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
703 (GC
) m_textGC
, xx
, yy
, ww
, hh
);
705 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
707 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
709 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
710 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
712 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
713 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
715 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
717 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
719 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
720 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
722 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
723 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
725 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
727 if (m_brush
.GetStyle() == wxSTIPPLE
)
729 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
730 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
731 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
733 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
734 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
736 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
740 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
741 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
745 if (m_pen
.GetStyle () != wxTRANSPARENT
)
747 XDrawRectangle( (Display
*) m_display
, (Window
) m_window
,
748 (GC
) m_penGC
, xx
, yy
, ww
, hh
);
752 CalcBoundingBox( x
, y
);
753 CalcBoundingBox( x
+ width
, y
+ height
);
754 wxLogDebug("Drawing rectangle at %d, %d (%dx%d)", x
, y
, width
, height
);
757 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
762 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
764 wxCHECK_RET( Ok(), wxT("invalid window dc") );
766 wxCoord xx
= XLOG2DEV(x
);
767 wxCoord yy
= YLOG2DEV(y
);
768 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
769 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
771 // CMB: handle -ve width and/or height
772 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
773 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
777 if (m_brush
.GetStyle() != wxTRANSPARENT
)
779 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
781 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
782 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
783 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
785 XFillArc( (Display
*) m_display
, (Window
) m_window
,
786 (GC
) m_textGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
788 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
790 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
792 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
793 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
795 XFillArc( (Display
*) m_display
, (Window
) m_window
,
796 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
798 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
800 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
802 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
803 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
805 XFillArc( (Display
*) m_display
, (Window
) m_window
,
806 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
808 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
810 if (m_brush
.GetStyle() == wxSTIPPLE
)
812 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
813 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
814 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
816 XFillArc( (Display
*) m_display
, (Window
) m_window
,
817 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
819 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
823 XFillArc( (Display
*) m_display
, (Window
) m_window
,
824 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
828 if (m_pen
.GetStyle () != wxTRANSPARENT
)
830 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
831 (GC
) m_penGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
835 CalcBoundingBox( x
, y
);
836 CalcBoundingBox( x
+ width
, y
+ height
);
839 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
843 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
844 wxCoord x
, wxCoord y
,
847 wxCHECK_RET( Ok(), wxT("invalid window dc") );
849 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
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
);
1253 if ((xfont
->min_byte1
== 0) && (xfont
->max_byte1
== 0))
1255 XDrawString( (Display
*) m_display
, (Window
) m_window
,
1256 (GC
) m_textGC
, x
, y
+ xfont
->ascent
, text
.c_str(), text
.Len() );
1260 if (m_font
.GetUnderlined())
1262 wxCoord ul_y
= y
+ font
->ascent
;
1263 if (font
->descent
> 0) ul_y
++;
1264 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1267 width
= wxCoord(width
/ m_scaleX
);
1268 height
= wxCoord(height
/ m_scaleY
);
1270 CalcBoundingBox (x
+ width
, y
+ height
);
1271 CalcBoundingBox (x
, y
);
1275 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1280 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1281 wxCoord
*descent
, wxCoord
*externalLeading
,
1282 wxFont
*font
) const
1284 wxCHECK_RET( Ok(), "invalid dc" );
1286 wxFont fontToUse
= m_font
;
1287 if (font
) fontToUse
= *font
;
1289 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
1291 XFontStruct
*xfont
= (XFontStruct
*) fontToUse
.GetFontStruct( m_scaleY
, m_display
);
1293 wxCHECK_RET( xfont
, wxT("invalid font") );
1295 int direction
, ascent
, descent2
;
1296 XCharStruct overall
;
1298 XTextExtents( xfont
, string
.c_str(), string
.Len(), &direction
,
1299 &ascent
, &descent2
, &overall
);
1302 *width
= (wxCoord
)( overall
.width
/ m_scaleX
);
1304 *height
= (wxCoord
)((ascent
+ descent2
) / m_scaleY
);
1306 *descent
= (wxCoord
)(descent2
/ m_scaleY
);
1307 if (externalLeading
)
1308 *externalLeading
= 0; // ??
1311 wxCoord
wxWindowDC::GetCharWidth() const
1313 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1315 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1317 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1319 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1321 int direction
, ascent
, descent
;
1322 XCharStruct overall
;
1324 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1326 return (wxCoord
)(overall
.width
/ m_scaleX
);
1329 wxCoord
wxWindowDC::GetCharHeight() const
1331 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1333 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1335 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1337 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1339 int direction
, ascent
, descent
;
1340 XCharStruct overall
;
1342 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1344 return (wxCoord
)((ascent
+descent
) / m_scaleY
);
1347 void wxWindowDC::Clear()
1349 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1351 if (!m_window
) return;
1353 /* - we either are a memory dc or have a window as the
1354 owner. anything else shouldn't happen.
1355 - we don't use gdk_window_clear() as we don't set
1356 the window's background colour anymore. it is too
1357 much pain to keep the DC's and the window's back-
1358 ground colour in synch. */
1363 m_owner
->GetSize( &width
, &height
);
1364 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1371 GetSize( &width
, &height
);
1372 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1377 void wxWindowDC::SetFont( const wxFont
&font
)
1379 wxCHECK_RET( Ok(), "invalid dc" );
1384 void wxWindowDC::SetPen( const wxPen
&pen
)
1386 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1388 if (m_pen
== pen
) return;
1392 if (!m_pen
.Ok()) return;
1394 if (!m_window
) return;
1396 int width
= m_pen
.GetWidth();
1399 // CMB: if width is non-zero scale it with the dc
1404 // X doesn't allow different width in x and y and so we take
1407 ( fabs((double) XLOG2DEVREL(width
)) +
1408 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1412 static const wxX11Dash dotted
[] = {1, 1};
1413 static const wxX11Dash short_dashed
[] = {2, 2};
1414 static const wxX11Dash long_dashed
[] = {2, 4};
1415 static const wxX11Dash dotted_dashed
[] = {3, 3, 1, 3};
1417 // We express dash pattern in pen width unit, so we are
1418 // independent of zoom factor and so on...
1420 const wxX11Dash
*req_dash
;
1422 int lineStyle
= LineSolid
;
1423 switch (m_pen
.GetStyle())
1427 lineStyle
= LineOnOffDash
;
1428 req_nb_dash
= m_pen
.GetDashCount();
1429 req_dash
= (wxX11Dash
*)m_pen
.GetDash();
1434 lineStyle
= LineOnOffDash
;
1441 lineStyle
= LineOnOffDash
;
1443 req_dash
= long_dashed
;
1448 lineStyle
= LineOnOffDash
;
1450 req_dash
= short_dashed
;
1455 // lineStyle = LineDoubleDash;
1456 lineStyle
= LineOnOffDash
;
1458 req_dash
= dotted_dashed
;
1463 case wxSTIPPLE_MASK_OPAQUE
:
1468 lineStyle
= LineSolid
;
1469 req_dash
= (wxX11Dash
*)NULL
;
1475 int capStyle
= CapRound
;
1476 switch (m_pen
.GetCap())
1478 case wxCAP_PROJECTING
: { capStyle
= CapProjecting
; break; }
1479 case wxCAP_BUTT
: { capStyle
= CapButt
; break; }
1486 capStyle
= CapNotLast
;
1490 capStyle
= CapRound
;
1496 int joinStyle
= JoinRound
;
1497 switch (m_pen
.GetJoin())
1499 case wxJOIN_BEVEL
: { joinStyle
= JoinBevel
; break; }
1500 case wxJOIN_MITER
: { joinStyle
= JoinMiter
; break; }
1502 default: { joinStyle
= JoinRound
; break; }
1505 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1507 m_pen
.GetColour().CalcPixel( m_cmap
);
1508 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
1511 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1513 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1515 if (m_brush
== brush
) return;
1519 if (!m_brush
.Ok()) return;
1521 if (!m_window
) return;
1523 m_brush
.GetColour().CalcPixel( m_cmap
);
1524 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
1526 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
1528 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1530 if (m_brush
.GetStipple()->GetPixmap())
1532 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillTiled
);
1533 XSetTile( (Display
*) m_display
, (GC
) m_brushGC
, (Pixmap
) m_brush
.GetStipple()->GetPixmap() );
1537 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1538 // XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1542 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1544 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillOpaqueStippled
);
1545 // XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1548 if (IS_HATCH(m_brush
.GetStyle()))
1550 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1551 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1552 XSetStipple( (Display
*) m_display
, (GC
) m_brushGC
, hatches
[num
] );
1556 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1558 /* CMB 21/7/98: Added SetBackground. Sets background brush
1559 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1561 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1563 if (m_backgroundBrush
== brush
) return;
1565 m_backgroundBrush
= brush
;
1567 if (!m_backgroundBrush
.Ok()) return;
1569 if (!m_window
) return;
1571 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1572 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, m_backgroundBrush
.GetColour().GetPixel() );
1573 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, m_backgroundBrush
.GetColour().GetPixel() );
1574 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1575 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1577 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
1579 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1581 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1583 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillTiled
);
1584 XSetTile( (Display
*) m_display
, (GC
) m_bgGC
, (Pixmap
) m_backgroundBrush
.GetStipple()->GetPixmap() );
1588 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1589 // XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
1593 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1595 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1596 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1597 XSetStipple( (Display
*) m_display
, (GC
) m_bgGC
, hatches
[num
] );
1601 void wxWindowDC::SetLogicalFunction( int function
)
1603 wxCHECK_RET( Ok(), "invalid dc" );
1607 if (m_logicalFunction
== function
)
1610 // VZ: shouldn't this be a CHECK?
1617 x_function
= GXclear
;
1623 x_function
= GXinvert
;
1626 x_function
= GXorReverse
;
1629 x_function
= GXandReverse
;
1638 x_function
= GXandInverted
;
1641 x_function
= GXnoop
;
1647 x_function
= GXequiv
;
1650 x_function
= GXcopyInverted
;
1653 x_function
= GXorInverted
;
1656 x_function
= GXnand
;
1663 x_function
= GXcopy
;
1667 XSetFunction( (Display
*) m_display
, (GC
) m_penGC
, x_function
);
1668 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, x_function
);
1670 // to stay compatible with wxMSW, we don't apply ROPs to the text
1671 // operations (i.e. DrawText/DrawRotatedText).
1672 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1673 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, x_function
);
1675 m_logicalFunction
= function
;
1678 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1680 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1682 // don't set m_textForegroundColour to an invalid colour as we'd crash
1683 // later then (we use m_textForegroundColour.GetColor() without checking
1685 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1688 m_textForegroundColour
= col
;
1692 m_textForegroundColour
.CalcPixel( m_cmap
);
1693 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
1697 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1699 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1702 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1705 m_textBackgroundColour
= col
;
1709 m_textBackgroundColour
.CalcPixel( m_cmap
);
1710 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
1714 void wxWindowDC::SetBackgroundMode( int mode
)
1716 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1718 m_backgroundMode
= mode
;
1720 if (!m_window
) return;
1722 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1723 // transparent/solid background mode
1725 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1727 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
,
1728 (m_backgroundMode
== wxTRANSPARENT
) ? FillStippled
: FillOpaqueStippled
);
1732 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1738 /* Use GetXColormap */
1739 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1740 (Colormap
) palette
.GetXColormap());
1742 /* Use wxGetMainColormap */
1743 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1744 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1749 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1751 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1753 if (!m_window
) return;
1756 rect
.x
= XLOG2DEV(x
);
1757 rect
.y
= YLOG2DEV(y
);
1758 rect
.width
= XLOG2DEVREL(width
);
1759 rect
.height
= YLOG2DEVREL(height
);
1761 if (!m_currentClippingRegion
.IsNull())
1762 m_currentClippingRegion
.Intersect( rect
);
1764 m_currentClippingRegion
.Union( rect
);
1766 #if USE_PAINT_REGION
1767 if (!m_paintClippingRegion
.IsNull())
1768 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1771 wxCoord xx
, yy
, ww
, hh
;
1772 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1773 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1775 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1776 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1777 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1778 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1781 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
1783 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1787 DestroyClippingRegion();
1791 if (!m_window
) return;
1793 if (!m_currentClippingRegion
.IsNull())
1794 m_currentClippingRegion
.Intersect( region
);
1796 m_currentClippingRegion
.Union( region
);
1798 #if USE_PAINT_REGION
1799 if (!m_paintClippingRegion
.IsNull())
1800 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1803 wxCoord xx
, yy
, ww
, hh
;
1804 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1805 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1807 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1808 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1809 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1810 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1813 void wxWindowDC::DestroyClippingRegion()
1815 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1817 wxDC::DestroyClippingRegion();
1819 m_currentClippingRegion
.Clear();
1821 #if USE_PAINT_REGION
1822 if (!m_paintClippingRegion
.IsEmpty())
1823 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1826 if (!m_window
) return;
1828 if (m_currentClippingRegion
.IsEmpty())
1830 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
1831 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
1832 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
1833 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
1837 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1838 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1839 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1840 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1844 void wxWindowDC::Destroy()
1846 if (m_penGC
) wxFreePoolGC( (GC
) m_penGC
);
1848 if (m_brushGC
) wxFreePoolGC( (GC
) m_brushGC
);
1850 if (m_textGC
) wxFreePoolGC( (GC
) m_textGC
);
1852 if (m_bgGC
) wxFreePoolGC( (GC
) m_bgGC
);
1856 void wxWindowDC::ComputeScaleAndOrigin()
1858 /* CMB: copy scale to see if it changes */
1859 double origScaleX
= m_scaleX
;
1860 double origScaleY
= m_scaleY
;
1862 wxDC::ComputeScaleAndOrigin();
1864 /* CMB: if scale has changed call SetPen to recalulate the line width */
1865 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1868 /* this is a bit artificial, but we need to force wxDC to think
1869 the pen has changed */
1876 wxSize
wxWindowDC::GetPPI() const
1878 return wxSize(100, 100);
1881 int wxWindowDC::GetDepth() const
1883 wxFAIL_MSG(wxT("not implemented"));
1888 // ----------------------------------------------------------------------------
1890 // ----------------------------------------------------------------------------
1892 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
1894 wxPaintDC::wxPaintDC(wxWindow
* win
)
1897 #if USE_PAINT_REGION
1898 if (!win
->GetClipPaintRegion())
1901 m_paintClippingRegion
= win
->GetUpdateRegion();
1902 Region region
= (Region
) m_paintClippingRegion
.GetX11Region();
1905 m_paintClippingRegion
= win
->GetUpdateRegion();
1906 Region region2
= (Region
) m_paintClippingRegion
.GetX11Region();
1909 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1911 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, region2
);
1912 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, region2
);
1913 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, region2
);
1914 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, region2
);
1917 #endif // USE_PAINT_REGION
1920 //-----------------------------------------------------------------------------
1922 //-----------------------------------------------------------------------------
1924 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
1926 wxClientDC::wxClientDC( wxWindow
*win
)
1929 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
1931 #ifdef __WXUNIVERSAL__
1932 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
1933 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
1934 wxSize size
= win
->GetClientSize();
1935 SetClippingRegion(wxPoint(0, 0), size
);
1936 #endif // __WXUNIVERSAL__
1939 void wxClientDC::DoGetSize(int *width
, int *height
) const
1941 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
1943 m_owner
->GetClientSize( width
, height
);
1946 // ----------------------------------------------------------------------------
1948 // ----------------------------------------------------------------------------
1950 class wxDCModule
: public wxModule
1957 DECLARE_DYNAMIC_CLASS(wxDCModule
)
1960 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
1962 bool wxDCModule::OnInit()
1968 void wxDCModule::OnExit()