]>
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
);
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
);
348 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
350 wxCHECK_RET( Ok(), wxT("invalid window dc") );
352 if (m_pen
.GetStyle() != wxTRANSPARENT
)
357 wxCoord xx
= XLOG2DEV(x
);
358 wxCoord yy
= YLOG2DEV(y
);
361 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
362 (GC
) m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
363 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
364 (GC
) m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
369 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
371 wxCHECK_RET( Ok(), wxT("invalid window dc") );
373 wxCoord xx1
= XLOG2DEV(x1
);
374 wxCoord yy1
= YLOG2DEV(y1
);
375 wxCoord xx2
= XLOG2DEV(x2
);
376 wxCoord yy2
= YLOG2DEV(y2
);
377 wxCoord xxc
= XLOG2DEV(xc
);
378 wxCoord yyc
= YLOG2DEV(yc
);
379 double dx
= xx1
- xxc
;
380 double dy
= yy1
- yyc
;
381 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
382 wxCoord r
= (wxCoord
)radius
;
383 double radius1
, radius2
;
385 if (xx1
== xx2
&& yy1
== yy2
)
393 radius1
= radius2
= 0.0;
397 radius1
= (xx1
- xxc
== 0) ?
398 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
399 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
400 radius2
= (xx2
- xxc
== 0) ?
401 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
402 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
404 wxCoord alpha1
= wxCoord(radius1
* 64.0);
405 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
406 while (alpha2
<= 0) alpha2
+= 360*64;
407 while (alpha1
> 360*64) alpha1
-= 360*64;
411 if (m_brush
.GetStyle() != wxTRANSPARENT
)
413 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
415 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
416 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
417 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
419 XFillArc( (Display
*) m_display
, (Window
) m_window
,
420 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
422 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
424 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
426 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
427 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
429 XFillArc( (Display
*) m_display
, (Window
) m_window
,
430 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
432 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
434 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
436 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
437 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
439 XFillArc( (Display
*) m_display
, (Window
) m_window
,
440 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
442 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
444 if (m_brush
.GetStyle() == wxSTIPPLE
)
446 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
447 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
448 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
450 XFillArc( (Display
*) m_display
, (Window
) m_window
,
451 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
453 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
457 XFillArc( (Display
*) m_display
, (Window
) m_window
,
458 (GC
) m_brushGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
462 if (m_pen
.GetStyle() != wxTRANSPARENT
)
464 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
465 (GC
) m_penGC
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
467 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
468 (GC
) m_penGC
, xx1
, yy1
, xxc
, yyc
);
470 XDrawLine( (Display
*) m_display
, (Window
) m_window
,
471 (GC
) m_penGC
, xxc
, yyc
, xx2
, yy2
);
475 CalcBoundingBox (x1
, y1
);
476 CalcBoundingBox (x2
, y2
);
479 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
481 wxCHECK_RET( Ok(), wxT("invalid window dc") );
483 wxCoord xx
= XLOG2DEV(x
);
484 wxCoord yy
= YLOG2DEV(y
);
485 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
486 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
488 // CMB: handle -ve width and/or height
489 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
490 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
494 wxCoord start
= wxCoord(sa
* 64.0);
495 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
497 if (m_brush
.GetStyle() != wxTRANSPARENT
)
499 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
501 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
502 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
503 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
505 XFillArc( (Display
*) m_display
, (Window
) m_window
,
506 (GC
) m_textGC
, xx
, yy
, ww
, hh
, start
, end
);
508 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
510 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
512 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
513 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
515 XFillArc( (Display
*) m_display
, (Window
) m_window
,
516 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
518 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
520 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
522 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
523 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
525 XFillArc( (Display
*) m_display
, (Window
) m_window
,
526 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
528 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
530 if (m_brush
.GetStyle() == wxSTIPPLE
)
532 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
533 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
534 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
536 XFillArc( (Display
*) m_display
, (Window
) m_window
,
537 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
539 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
543 XFillArc( (Display
*) m_display
, (Window
) m_window
,
544 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, start
, end
);
548 if (m_pen
.GetStyle() != wxTRANSPARENT
)
550 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
551 (GC
) m_penGC
, xx
, yy
, ww
, hh
, start
, end
);
555 CalcBoundingBox (x
, y
);
556 CalcBoundingBox (x
+ width
, y
+ height
);
559 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
561 wxCHECK_RET( Ok(), wxT("invalid window dc") );
563 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
564 XDrawPoint( (Display
*) m_display
, (Window
) m_window
,
565 (GC
) m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
567 CalcBoundingBox (x
, y
);
570 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
572 wxCHECK_RET( Ok(), wxT("invalid window dc") );
574 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
577 XPoint
*xpoints
= new XPoint
[n
];
578 for (int i
= 0; i
< n
; i
++)
580 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
581 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
583 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
585 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
, 0 );
590 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[],
591 wxCoord xoffset
, wxCoord yoffset
, int fillStyle
)
593 wxCHECK_RET( Ok(), wxT("invalid window dc") );
597 XPoint
*xpoints
= new XPoint
[n
+ 1];
599 for (i
= 0; i
< n
; i
++)
601 xpoints
[i
].x
= XLOG2DEV (points
[i
].x
+ xoffset
);
602 xpoints
[i
].y
= YLOG2DEV (points
[i
].y
+ yoffset
);
604 CalcBoundingBox (points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
609 if (m_brush
.GetStyle() != wxTRANSPARENT
)
612 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
614 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
615 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
616 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
618 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
619 (GC
) m_textGC
, xpoints
, n
, Complex
, 0);
621 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
623 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
625 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
626 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
628 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
629 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
631 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
633 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
635 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
636 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
638 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
639 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
641 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
643 if (m_brush
.GetStyle() == wxSTIPPLE
)
645 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
646 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
647 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
649 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
650 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
652 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
656 XFillPolygon( (Display
*) m_display
, (Window
) m_window
,
657 (GC
) m_brushGC
, xpoints
, n
, Complex
, 0);
661 if (m_pen
.GetStyle () != wxTRANSPARENT
)
663 // Close figure for XDrawLines
664 xpoints
[i
].x
= xpoints
[0].x
;
665 xpoints
[i
].y
= xpoints
[0].y
;
667 XDrawLines( (Display
*) m_display
, (Window
) m_window
, (GC
) m_penGC
, xpoints
, n
+ 1, 0);
674 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
676 wxCHECK_RET( Ok(), wxT("invalid window dc") );
678 wxCoord xx
= XLOG2DEV(x
);
679 wxCoord yy
= YLOG2DEV(y
);
680 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
681 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
683 // CMB: draw nothing if transformed w or h is 0
684 if (ww
== 0 || hh
== 0) return;
686 // CMB: handle -ve width and/or height
687 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
688 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
692 if (m_brush
.GetStyle() != wxTRANSPARENT
)
694 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
696 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
697 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
698 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
700 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
701 (GC
) m_textGC
, xx
, yy
, ww
, hh
);
703 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
705 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
707 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
708 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
710 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
711 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
713 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
715 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
717 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
718 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
720 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
721 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
723 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
725 if (m_brush
.GetStyle() == wxSTIPPLE
)
727 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
728 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
729 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
731 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
732 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
734 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
738 XFillRectangle( (Display
*) m_display
, (Window
) m_window
,
739 (GC
) m_brushGC
, xx
, yy
, ww
, hh
);
743 if (m_pen
.GetStyle () != wxTRANSPARENT
)
745 XDrawRectangle( (Display
*) m_display
, (Window
) m_window
,
746 (GC
) m_penGC
, xx
, yy
, ww
, hh
);
750 CalcBoundingBox( x
, y
);
751 CalcBoundingBox( x
+ width
, y
+ height
);
754 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
759 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
761 wxCHECK_RET( Ok(), wxT("invalid window dc") );
763 wxCoord xx
= XLOG2DEV(x
);
764 wxCoord yy
= YLOG2DEV(y
);
765 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
766 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
768 // CMB: handle -ve width and/or height
769 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
770 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
774 if (m_brush
.GetStyle() != wxTRANSPARENT
)
776 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
778 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
,
779 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
780 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
782 XFillArc( (Display
*) m_display
, (Window
) m_window
,
783 (GC
) m_textGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
785 XSetTSOrigin( (Display
*) m_display
, (GC
) m_textGC
, 0, 0 );
787 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
789 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
790 m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
792 XFillArc( (Display
*) m_display
, (Window
) m_window
,
793 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
795 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
797 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
799 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
800 m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
802 XFillArc( (Display
*) m_display
, (Window
) m_window
,
803 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
805 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
807 if (m_brush
.GetStyle() == wxSTIPPLE
)
809 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
,
810 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
811 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
813 XFillArc( (Display
*) m_display
, (Window
) m_window
,
814 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
816 XSetTSOrigin( (Display
*) m_display
, (GC
) m_brushGC
, 0, 0 );
820 XFillArc( (Display
*) m_display
, (Window
) m_window
,
821 (GC
) m_brushGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
825 if (m_pen
.GetStyle () != wxTRANSPARENT
)
827 XDrawArc( (Display
*) m_display
, (Window
) m_window
,
828 (GC
) m_penGC
, xx
, yy
, ww
, hh
, 0, 360*64 );
832 CalcBoundingBox( x
, y
);
833 CalcBoundingBox( x
+ width
, y
+ height
);
836 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
840 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
841 wxCoord x
, wxCoord y
,
844 wxCHECK_RET( Ok(), wxT("invalid window dc") );
846 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
849 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
851 /* scale/translate size and position */
852 int xx
= XLOG2DEV(x
);
853 int yy
= YLOG2DEV(y
);
855 int w
= bitmap
.GetWidth();
856 int h
= bitmap
.GetHeight();
858 CalcBoundingBox( x
, y
);
859 CalcBoundingBox( x
+ w
, y
+ h
);
861 if (!m_window
) return;
863 int ww
= XLOG2DEVREL(w
);
864 int hh
= YLOG2DEVREL(h
);
866 /* compare to current clipping region */
867 if (!m_currentClippingRegion
.IsNull())
869 wxRegion
tmp( xx
,yy
,ww
,hh
);
870 tmp
.Intersect( m_currentClippingRegion
);
875 /* scale bitmap if required */
877 if ((w
!= ww
) || (h
!= hh
))
879 wxImage
image( bitmap
);
880 image
.Rescale( ww
, hh
);
882 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
884 use_bitmap
= image
.ConvertToBitmap();
891 /* apply mask if any */
892 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
893 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
897 GdkBitmap
*new_mask
= (GdkBitmap
*) 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 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
923 gdk_gc_set_clip_mask( m_textGC
, mask
);
924 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
929 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
931 gdk_gc_set_clip_mask( m_penGC
, mask
);
932 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
935 gdk_bitmap_unref( new_mask
);
938 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
939 drawing a mono-bitmap (XBitmap) we use the current text GC */
941 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
943 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
945 /* remove mask again if any */
950 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
951 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
952 if (!m_currentClippingRegion
.IsNull())
953 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
957 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
958 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
959 if (!m_currentClippingRegion
.IsNull())
960 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
966 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
967 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
,
968 wxCoord xsrcMask
, wxCoord ysrcMask
)
970 /* this is the nth try to get this utterly useless function to
971 work. it now completely ignores the scaling or translation
972 of the source dc, but scales correctly on the target dc and
973 knows about possible mask information in a memory dc. */
975 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
977 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
979 if (!m_window
) return FALSE
;
981 // transform the source DC coords to the device ones
982 xsrc
= source
->XLOG2DEV(xsrc
);
983 ysrc
= source
->YLOG2DEV(ysrc
);
985 wxClientDC
*srcDC
= (wxClientDC
*)source
;
986 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
988 bool use_bitmap_method
= FALSE
;
989 bool is_mono
= FALSE
;
991 /* TODO: use the mask origin when drawing transparently */
992 if (xsrcMask
== -1 && ysrcMask
== -1)
994 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
998 if (srcDC
->m_isMemDC
)
1000 if (!memDC
->m_selected
.Ok()) return FALSE
;
1002 /* we use the "XCopyArea" way to copy a memory dc into
1003 y different window if the memory dc BOTH
1004 a) doesn't have any mask or its mask isn't used
1008 if (useMask
&& (memDC
->m_selected
.GetMask()))
1010 /* we HAVE TO use the direct way for memory dcs
1011 that have mask since the XCopyArea doesn't know
1013 use_bitmap_method
= TRUE
;
1015 else if (memDC
->m_selected
.GetDepth() == 1)
1017 /* we HAVE TO use the direct way for memory dcs
1018 that are bitmaps because XCopyArea doesn't cope
1019 with different bit depths */
1021 use_bitmap_method
= TRUE
;
1023 else if ((xsrc
== 0) && (ysrc
== 0) &&
1024 (width
== memDC
->m_selected
.GetWidth()) &&
1025 (height
== memDC
->m_selected
.GetHeight()))
1027 /* we SHOULD use the direct way if all of the bitmap
1028 in the memory dc is copied in which case XCopyArea
1029 wouldn't be able able to boost performace by reducing
1030 the area to be scaled */
1031 use_bitmap_method
= TRUE
;
1035 use_bitmap_method
= FALSE
;
1039 CalcBoundingBox( xdest
, ydest
);
1040 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1042 /* scale/translate size and position */
1043 wxCoord xx
= XLOG2DEV(xdest
);
1044 wxCoord yy
= YLOG2DEV(ydest
);
1046 wxCoord ww
= XLOG2DEVREL(width
);
1047 wxCoord hh
= YLOG2DEVREL(height
);
1049 /* compare to current clipping region */
1050 if (!m_currentClippingRegion
.IsNull())
1052 wxRegion
tmp( xx
,yy
,ww
,hh
);
1053 tmp
.Intersect( m_currentClippingRegion
);
1058 int old_logical_func
= m_logicalFunction
;
1059 SetLogicalFunction( logical_func
);
1061 if (use_bitmap_method
)
1063 /* scale/translate bitmap size */
1064 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1065 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1067 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1068 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1070 /* scale bitmap if required */
1071 wxBitmap use_bitmap
;
1073 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1075 wxImage
image( memDC
->m_selected
);
1076 image
= image
.Scale( bm_ww
, bm_hh
);
1079 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
1081 use_bitmap
= image
.ConvertToBitmap();
1085 use_bitmap
= memDC
->m_selected
;
1088 /* apply mask if any */
1089 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1090 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1092 if (useMask
&& mask
)
1094 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1095 if (!m_currentClippingRegion
.IsNull())
1098 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1099 GdkGC
*gc
= gdk_gc_new( new_mask
);
1101 gdk_gc_set_foreground( gc
, &col
);
1102 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1104 gdk_gc_set_background( gc
, &col
);
1106 gdk_gc_set_foreground( gc
, &col
);
1107 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1108 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1109 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1110 gdk_gc_set_stipple( gc
, mask
);
1111 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1118 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1120 gdk_gc_set_clip_mask( m_textGC
, mask
);
1121 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1126 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1128 gdk_gc_set_clip_mask( m_penGC
, mask
);
1129 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1132 gdk_bitmap_unref( new_mask
);
1135 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1136 drawing a mono-bitmap (XBitmap) we use the current text GC */
1139 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1141 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1143 /* remove mask again if any */
1144 if (useMask
&& mask
)
1148 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1149 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1150 if (!m_currentClippingRegion
.IsNull())
1151 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1155 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1156 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1157 if (!m_currentClippingRegion
.IsNull())
1158 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1162 else /* use_bitmap_method */
1164 if ((width
!= ww
) || (height
!= hh
))
1166 /* draw source window into a bitmap as we cannot scale
1167 a window in contrast to a bitmap. this would actually
1168 work with memory dcs as well, but we'd lose the mask
1169 information and waste one step in this process since
1170 a memory already has a bitmap. all this is slightly
1171 inefficient as we could take an XImage directly from
1172 an X window, but we'd then also have to care that
1173 the window is not outside the screen (in which case
1174 we'd get a BadMatch or what not).
1175 Is a double XGetImage and combined XGetPixel and
1176 XPutPixel really faster? I'm not sure. look at wxXt
1177 for a different implementation of the same problem. */
1179 wxBitmap
bitmap( width
, height
);
1181 /* copy including child window contents */
1182 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1183 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1185 xsrc
, ysrc
, width
, height
);
1186 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1189 wxImage
image( bitmap
);
1190 image
= image
.Scale( ww
, hh
);
1192 /* convert to bitmap */
1193 bitmap
= image
.ConvertToBitmap();
1195 /* draw scaled bitmap */
1196 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1201 /* No scaling and not a memory dc with a mask either */
1203 /* copy including child window contents */
1204 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1205 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1207 xsrc
, ysrc
, width
, height
);
1208 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1212 SetLogicalFunction( old_logical_func
);
1219 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1221 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1223 if (!m_window
) return;
1225 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1227 wxCHECK_RET( xfont
, wxT("invalid font") );
1233 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1234 wxCoord height
= font
->ascent
+ font
->descent
;
1236 if ( m_backgroundMode
== wxSOLID
)
1238 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1239 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1240 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1244 XSetFont( (Display
*) m_display
, (GC
) m_textGC
, xfont
->fid
);
1245 if ((xfont
->min_byte1
== 0) && (xfont
->max_byte1
== 0))
1247 XDrawString( (Display
*) m_display
, (Window
) m_window
,
1248 (GC
) m_textGC
, x
, y
, text
.c_str(), text
.Len() );
1252 if (m_font
.GetUnderlined())
1254 wxCoord ul_y
= y
+ font
->ascent
;
1255 if (font
->descent
> 0) ul_y
++;
1256 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1259 width
= wxCoord(width
/ m_scaleX
);
1260 height
= wxCoord(height
/ m_scaleY
);
1262 CalcBoundingBox (x
+ width
, y
+ height
);
1263 CalcBoundingBox (x
, y
);
1267 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1272 void wxWindowDC::DoGetTextExtent( const wxString
&string
, wxCoord
*width
, wxCoord
*height
,
1273 wxCoord
*descent
, wxCoord
*externalLeading
,
1274 wxFont
*font
) const
1276 wxCHECK_RET( Ok(), "invalid dc" );
1278 wxFont fontToUse
= m_font
;
1279 if (font
) fontToUse
= *font
;
1281 wxCHECK_RET( fontToUse
.Ok(), "invalid font" );
1283 XFontStruct
*xfont
= (XFontStruct
*) fontToUse
.GetFontStruct( m_scaleY
, m_display
);
1285 wxCHECK_RET( xfont
, wxT("invalid font") );
1287 int direction
, ascent
, descent2
;
1288 XCharStruct overall
;
1290 XTextExtents( xfont
, string
.c_str(), string
.Len(), &direction
,
1291 &ascent
, &descent2
, &overall
);
1294 *width
= (wxCoord
)( overall
.width
/ m_scaleX
);
1296 *height
= (wxCoord
)((ascent
+ descent2
) / m_scaleY
);
1298 *descent
= (wxCoord
)(descent2
/ m_scaleY
);
1299 if (externalLeading
)
1300 *externalLeading
= 0; // ??
1303 wxCoord
wxWindowDC::GetCharWidth() const
1305 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1307 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1309 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1311 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1313 int direction
, ascent
, descent
;
1314 XCharStruct overall
;
1316 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1318 return (wxCoord
)(overall
.width
/ m_scaleX
);
1321 wxCoord
wxWindowDC::GetCharHeight() const
1323 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1325 wxCHECK_MSG( m_font
.Ok(), 0, "invalid font" );
1327 XFontStruct
*xfont
= (XFontStruct
*) m_font
.GetFontStruct( m_scaleY
, m_display
);
1329 wxCHECK_MSG( xfont
, 0, wxT("invalid font") );
1331 int direction
, ascent
, descent
;
1332 XCharStruct overall
;
1334 XTextExtents( xfont
, "H", 1, &direction
, &ascent
, &descent
, &overall
);
1336 return (wxCoord
)((ascent
+descent
) / m_scaleY
);
1339 void wxWindowDC::Clear()
1341 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1343 if (!m_window
) return;
1345 /* - we either are a memory dc or have a window as the
1346 owner. anything else shouldn't happen.
1347 - we don't use gdk_window_clear() as we don't set
1348 the window's background colour anymore. it is too
1349 much pain to keep the DC's and the window's back-
1350 ground colour in synch. */
1355 m_owner
->GetSize( &width
, &height
);
1356 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1363 GetSize( &width
, &height
);
1364 XFillRectangle( (Display
*) m_display
, (Window
) m_window
, (GC
) m_bgGC
, 0, 0, width
, height
);
1369 void wxWindowDC::SetFont( const wxFont
&font
)
1371 wxCHECK_RET( Ok(), "invalid dc" );
1376 void wxWindowDC::SetPen( const wxPen
&pen
)
1378 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1380 if (m_pen
== pen
) return;
1384 if (!m_pen
.Ok()) return;
1386 if (!m_window
) return;
1388 int width
= m_pen
.GetWidth();
1391 // CMB: if width is non-zero scale it with the dc
1396 // X doesn't allow different width in x and y and so we take
1399 ( fabs((double) XLOG2DEVREL(width
)) +
1400 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1404 static const wxX11Dash dotted
[] = {1, 1};
1405 static const wxX11Dash short_dashed
[] = {2, 2};
1406 static const wxX11Dash long_dashed
[] = {2, 4};
1407 static const wxX11Dash dotted_dashed
[] = {3, 3, 1, 3};
1409 // We express dash pattern in pen width unit, so we are
1410 // independent of zoom factor and so on...
1412 const wxX11Dash
*req_dash
;
1414 int lineStyle
= LineSolid
;
1415 switch (m_pen
.GetStyle())
1419 lineStyle
= LineOnOffDash
;
1420 req_nb_dash
= m_pen
.GetDashCount();
1421 req_dash
= (wxX11Dash
*)m_pen
.GetDash();
1426 lineStyle
= LineOnOffDash
;
1433 lineStyle
= LineOnOffDash
;
1435 req_dash
= long_dashed
;
1440 lineStyle
= LineOnOffDash
;
1442 req_dash
= short_dashed
;
1447 // lineStyle = LineDoubleDash;
1448 lineStyle
= LineOnOffDash
;
1450 req_dash
= dotted_dashed
;
1455 case wxSTIPPLE_MASK_OPAQUE
:
1460 lineStyle
= LineSolid
;
1461 req_dash
= (wxX11Dash
*)NULL
;
1467 int capStyle
= CapRound
;
1468 switch (m_pen
.GetCap())
1470 case wxCAP_PROJECTING
: { capStyle
= CapProjecting
; break; }
1471 case wxCAP_BUTT
: { capStyle
= CapButt
; break; }
1478 capStyle
= CapNotLast
;
1482 capStyle
= CapRound
;
1488 int joinStyle
= JoinRound
;
1489 switch (m_pen
.GetJoin())
1491 case wxJOIN_BEVEL
: { joinStyle
= JoinBevel
; break; }
1492 case wxJOIN_MITER
: { joinStyle
= JoinMiter
; break; }
1494 default: { joinStyle
= JoinRound
; break; }
1497 XSetLineAttributes( (Display
*) m_display
, (GC
) m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1499 m_pen
.GetColour().CalcPixel( m_cmap
);
1500 XSetForeground( (Display
*) m_display
, (GC
) m_penGC
, m_pen
.GetColour().GetPixel() );
1503 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1505 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1507 if (m_brush
== brush
) return;
1511 if (!m_brush
.Ok()) return;
1513 if (!m_window
) return;
1515 m_brush
.GetColour().CalcPixel( m_cmap
);
1516 XSetForeground( (Display
*) m_display
, (GC
) m_brushGC
, m_brush
.GetColour().GetPixel() );
1518 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillSolid
);
1520 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1522 if (m_brush
.GetStipple()->GetPixmap())
1524 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillTiled
);
1525 XSetTile( (Display
*) m_display
, (GC
) m_brushGC
, (Pixmap
) m_brush
.GetStipple()->GetPixmap() );
1529 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1530 // XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1534 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1536 XSetFillStyle( (Display
*) m_display
, (GC
) m_textGC
, FillOpaqueStippled
);
1537 // XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1540 if (IS_HATCH(m_brush
.GetStyle()))
1542 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
, FillStippled
);
1543 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1544 XSetStipple( (Display
*) m_display
, (GC
) m_brushGC
, hatches
[num
] );
1548 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1550 /* CMB 21/7/98: Added SetBackground. Sets background brush
1551 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1553 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1555 if (m_backgroundBrush
== brush
) return;
1557 m_backgroundBrush
= brush
;
1559 if (!m_backgroundBrush
.Ok()) return;
1561 if (!m_window
) return;
1563 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1564 XSetBackground( (Display
*) m_display
, (GC
) m_brushGC
, m_backgroundBrush
.GetColour().GetPixel() );
1565 XSetBackground( (Display
*) m_display
, (GC
) m_penGC
, m_backgroundBrush
.GetColour().GetPixel() );
1566 XSetBackground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1567 XSetForeground( (Display
*) m_display
, (GC
) m_bgGC
, m_backgroundBrush
.GetColour().GetPixel() );
1569 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillSolid
);
1571 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1573 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1575 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillTiled
);
1576 XSetTile( (Display
*) m_display
, (GC
) m_bgGC
, (Pixmap
) m_backgroundBrush
.GetStipple()->GetPixmap() );
1580 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1581 // XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
1585 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1587 XSetFillStyle( (Display
*) m_display
, (GC
) m_bgGC
, FillStippled
);
1588 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1589 XSetStipple( (Display
*) m_display
, (GC
) m_bgGC
, hatches
[num
] );
1593 void wxWindowDC::SetLogicalFunction( int function
)
1595 wxCHECK_RET( Ok(), "invalid dc" );
1599 if (m_logicalFunction
== function
)
1602 // VZ: shouldn't this be a CHECK?
1609 x_function
= GXclear
;
1615 x_function
= GXinvert
;
1618 x_function
= GXorReverse
;
1621 x_function
= GXandReverse
;
1630 x_function
= GXandInverted
;
1633 x_function
= GXnoop
;
1639 x_function
= GXequiv
;
1642 x_function
= GXcopyInverted
;
1645 x_function
= GXorInverted
;
1648 x_function
= GXnand
;
1655 x_function
= GXcopy
;
1659 XSetFunction( (Display
*) m_display
, (GC
) m_penGC
, x_function
);
1660 XSetFunction( (Display
*) m_display
, (GC
) m_brushGC
, x_function
);
1662 // to stay compatible with wxMSW, we don't apply ROPs to the text
1663 // operations (i.e. DrawText/DrawRotatedText).
1664 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1665 XSetFunction( (Display
*) m_display
, (GC
) m_textGC
, x_function
);
1667 m_logicalFunction
= function
;
1670 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1672 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1674 // don't set m_textForegroundColour to an invalid colour as we'd crash
1675 // later then (we use m_textForegroundColour.GetColor() without checking
1677 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1680 m_textForegroundColour
= col
;
1684 m_textForegroundColour
.CalcPixel( m_cmap
);
1685 XSetForeground( (Display
*) m_display
, (GC
) m_textGC
, m_textForegroundColour
.GetPixel() );
1689 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1691 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1694 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1697 m_textBackgroundColour
= col
;
1701 m_textBackgroundColour
.CalcPixel( m_cmap
);
1702 XSetBackground( (Display
*) m_display
, (GC
) m_textGC
, m_textBackgroundColour
.GetPixel() );
1706 void wxWindowDC::SetBackgroundMode( int mode
)
1708 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1710 m_backgroundMode
= mode
;
1712 if (!m_window
) return;
1714 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1715 // transparent/solid background mode
1717 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1719 XSetFillStyle( (Display
*) m_display
, (GC
) m_brushGC
,
1720 (m_backgroundMode
== wxTRANSPARENT
) ? FillStippled
: FillOpaqueStippled
);
1724 void wxWindowDC::SetPalette( const wxPalette
& palette
)
1730 /* Use GetXColormap */
1731 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1732 (Colormap
) palette
.GetXColormap());
1734 /* Use wxGetMainColormap */
1735 XSetWindowColormap ((Display
*) m_display
, (Window
) m_window
->GetXWindow(),
1736 (Colormap
) wxTheApp
->GetMainColormap(m_display
));
1741 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1743 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1745 if (!m_window
) return;
1748 rect
.x
= XLOG2DEV(x
);
1749 rect
.y
= YLOG2DEV(y
);
1750 rect
.width
= XLOG2DEVREL(width
);
1751 rect
.height
= YLOG2DEVREL(height
);
1753 if (!m_currentClippingRegion
.IsNull())
1754 m_currentClippingRegion
.Intersect( rect
);
1756 m_currentClippingRegion
.Union( rect
);
1758 #if USE_PAINT_REGION
1759 if (!m_paintClippingRegion
.IsNull())
1760 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1763 wxCoord xx
, yy
, ww
, hh
;
1764 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1765 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1767 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1768 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1769 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1770 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1773 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
& region
)
1775 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1779 DestroyClippingRegion();
1783 if (!m_window
) return;
1785 if (!m_currentClippingRegion
.IsNull())
1786 m_currentClippingRegion
.Intersect( region
);
1788 m_currentClippingRegion
.Union( region
);
1790 #if USE_PAINT_REGION
1791 if (!m_paintClippingRegion
.IsNull())
1792 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1795 wxCoord xx
, yy
, ww
, hh
;
1796 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1797 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1799 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1800 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1801 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1802 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1805 void wxWindowDC::DestroyClippingRegion()
1807 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1809 wxDC::DestroyClippingRegion();
1811 m_currentClippingRegion
.Clear();
1813 #if USE_PAINT_REGION
1814 if (!m_paintClippingRegion
.IsEmpty())
1815 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1818 if (!m_window
) return;
1820 if (m_currentClippingRegion
.IsEmpty())
1822 XSetClipMask( (Display
*) m_display
, (GC
) m_penGC
, None
);
1823 XSetClipMask( (Display
*) m_display
, (GC
) m_brushGC
, None
);
1824 XSetClipMask( (Display
*) m_display
, (GC
) m_textGC
, None
);
1825 XSetClipMask( (Display
*) m_display
, (GC
) m_bgGC
, None
);
1829 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1830 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1831 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1832 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, (Region
) m_currentClippingRegion
.GetX11Region() );
1836 void wxWindowDC::Destroy()
1838 if (m_penGC
) wxFreePoolGC( (GC
) m_penGC
);
1840 if (m_brushGC
) wxFreePoolGC( (GC
) m_brushGC
);
1842 if (m_textGC
) wxFreePoolGC( (GC
) m_textGC
);
1844 if (m_bgGC
) wxFreePoolGC( (GC
) m_bgGC
);
1848 void wxWindowDC::ComputeScaleAndOrigin()
1850 /* CMB: copy scale to see if it changes */
1851 double origScaleX
= m_scaleX
;
1852 double origScaleY
= m_scaleY
;
1854 wxDC::ComputeScaleAndOrigin();
1856 /* CMB: if scale has changed call SetPen to recalulate the line width */
1857 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1860 /* this is a bit artificial, but we need to force wxDC to think
1861 the pen has changed */
1868 wxSize
wxWindowDC::GetPPI() const
1870 return wxSize(100, 100);
1873 int wxWindowDC::GetDepth() const
1875 wxFAIL_MSG(wxT("not implemented"));
1880 // ----------------------------------------------------------------------------
1882 // ----------------------------------------------------------------------------
1884 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
1886 wxPaintDC::wxPaintDC(wxWindow
* win
)
1889 #if USE_PAINT_REGION
1890 if (!win
->GetClipPaintRegion())
1893 m_paintClippingRegion
= win
->GetUpdateRegion();
1894 Region region
= (Region
) m_paintClippingRegion
.GetX11Region();
1897 m_paintClippingRegion
= win
->GetUpdateRegion();
1898 Region region2
= (Region
) m_paintClippingRegion
.GetX11Region();
1901 m_currentClippingRegion
.Union( m_paintClippingRegion
);
1903 XSetRegion( (Display
*) m_display
, (GC
) m_penGC
, region2
);
1904 XSetRegion( (Display
*) m_display
, (GC
) m_brushGC
, region2
);
1905 XSetRegion( (Display
*) m_display
, (GC
) m_textGC
, region2
);
1906 XSetRegion( (Display
*) m_display
, (GC
) m_bgGC
, region2
);
1909 #endif // USE_PAINT_REGION
1912 //-----------------------------------------------------------------------------
1914 //-----------------------------------------------------------------------------
1916 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
1918 wxClientDC::wxClientDC( wxWindow
*win
)
1921 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
1924 void wxClientDC::DoGetSize(int *width
, int *height
) const
1926 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
1928 m_owner
->GetClientSize( width
, height
);
1931 // ----------------------------------------------------------------------------
1933 // ----------------------------------------------------------------------------
1935 class wxDCModule
: public wxModule
1942 DECLARE_DYNAMIC_CLASS(wxDCModule
)
1945 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
1947 bool wxDCModule::OnInit()
1953 void wxDCModule::OnExit()