]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
non-pch build fixes
[wxWidgets.git] / src / x11 / dcclient.cpp
CommitLineData
83df96d6 1/////////////////////////////////////////////////////////////////////////////
670f9935 2// Name: src/x11/dcclient.cpp
83df96d6 3// Purpose: wxClientDC class
3cd0b8c5 4// Author: Julian Smart, Robert Roebling
83df96d6
JS
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
3cd0b8c5 8// Copyright: (c) Julian Smart, Robert Roebling
65571936 9// Licence: wxWindows licence
83df96d6
JS
10/////////////////////////////////////////////////////////////////////////////
11
670f9935
WS
12// for compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
83df96d6 15#include "wx/dcclient.h"
670f9935
WS
16
17#ifndef WX_PRECOMP
18 #include "wx/app.h"
cdccdfab 19 #include "wx/window.h"
18680f86 20 #include "wx/math.h"
155ecd4c 21 #include "wx/image.h"
02761f6c 22 #include "wx/module.h"
670f9935
WS
23#endif
24
2b5f62a0 25#include "wx/fontutil.h"
83df96d6 26
3cd0b8c5 27#include "wx/x11/private.h"
2b77c3fc
RR
28#include "wx/x11/dcclient.h"
29#include "wx/x11/dcmemory.h"
3cd0b8c5 30
2b5f62a0
VZ
31#if wxUSE_UNICODE
32#include "glib.h"
33#include "pango/pangox.h"
4ae1af05
MB
34#ifdef HAVE_PANGO_XFT
35 #include "pango/pangoxft.h"
36#endif
2b5f62a0
VZ
37
38#include "pango_x.cpp"
39#endif
40
3cd0b8c5
RR
41//-----------------------------------------------------------------------------
42// local defines
43//-----------------------------------------------------------------------------
83df96d6 44
6dd25d20
VZ
45// VZ: what is this for exactly??
46#define USE_PAINT_REGION 0
83df96d6 47
3cd0b8c5
RR
48//-----------------------------------------------------------------------------
49// local data
50//-----------------------------------------------------------------------------
83df96d6
JS
51
52#include "bdiag.xbm"
53#include "fdiag.xbm"
54#include "cdiag.xbm"
55#include "horiz.xbm"
56#include "verti.xbm"
57#include "cross.xbm"
3cd0b8c5 58#define num_hatches 6
83df96d6 59
3cd0b8c5
RR
60#define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
61#define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
83df96d6 62
3cd0b8c5
RR
63static Pixmap hatches[num_hatches];
64static Pixmap *hatch_bitmap = (Pixmap *) NULL;
65
66//-----------------------------------------------------------------------------
83df96d6 67// constants
3cd0b8c5 68//-----------------------------------------------------------------------------
83df96d6 69
3cd0b8c5 70const double RAD2DEG = 180.0 / M_PI;
83df96d6
JS
71
72// ----------------------------------------------------------------------------
3cd0b8c5 73// private functions
83df96d6
JS
74// ----------------------------------------------------------------------------
75
3cd0b8c5
RR
76static inline double dmax(double a, double b) { return a > b ? a : b; }
77static inline double dmin(double a, double b) { return a < b ? a : b; }
83df96d6 78
3cd0b8c5
RR
79static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
80
81//-----------------------------------------------------------------------------
82// Implement Pool of Graphic contexts. Creating them takes too much time.
83//-----------------------------------------------------------------------------
84
85#define GC_POOL_SIZE 200
86
87enum wxPoolGCType
88{
89 wxGC_ERROR = 0,
90 wxTEXT_MONO,
91 wxBG_MONO,
92 wxPEN_MONO,
93 wxBRUSH_MONO,
94 wxTEXT_COLOUR,
95 wxBG_COLOUR,
96 wxPEN_COLOUR,
97 wxBRUSH_COLOUR,
98 wxTEXT_SCREEN,
99 wxBG_SCREEN,
100 wxPEN_SCREEN,
101 wxBRUSH_SCREEN
102};
103
104struct wxGC
105{
106 GC m_gc;
107 wxPoolGCType m_type;
108 bool m_used;
109};
110
111static wxGC wxGCPool[GC_POOL_SIZE];
112
113static void wxInitGCPool()
114{
115 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) );
116}
83df96d6 117
3cd0b8c5 118static void wxCleanUpGCPool()
83df96d6 119{
3cd0b8c5
RR
120 for (int i = 0; i < GC_POOL_SIZE; i++)
121 {
122 if (wxGCPool[i].m_gc)
123 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc );
124 }
83df96d6
JS
125}
126
3cd0b8c5 127static GC wxGetPoolGC( Window window, wxPoolGCType type )
83df96d6 128{
3cd0b8c5
RR
129 for (int i = 0; i < GC_POOL_SIZE; i++)
130 {
131 if (!wxGCPool[i].m_gc)
132 {
133 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL );
134 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE );
135 wxGCPool[i].m_type = type;
ab9d0a8c 136 wxGCPool[i].m_used = false;
3cd0b8c5
RR
137 }
138 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
139 {
ab9d0a8c 140 wxGCPool[i].m_used = true;
3cd0b8c5
RR
141 return wxGCPool[i].m_gc;
142 }
143 }
144
145 wxFAIL_MSG( wxT("No GC available") );
146
147 return (GC) NULL;
83df96d6
JS
148}
149
3cd0b8c5
RR
150static void wxFreePoolGC( GC gc )
151{
152 for (int i = 0; i < GC_POOL_SIZE; i++)
153 {
154 if (wxGCPool[i].m_gc == gc)
155 {
ab9d0a8c 156 wxGCPool[i].m_used = false;
3cd0b8c5
RR
157 return;
158 }
159 }
160
161 wxFAIL_MSG( wxT("Wrong GC") );
162}
83df96d6
JS
163
164// ----------------------------------------------------------------------------
165// wxWindowDC
166// ----------------------------------------------------------------------------
167
2b77c3fc 168IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxX11DCImpl)
3cd0b8c5 169
2b77c3fc
RR
170wxWindowDCImpl::wxWindowDCImpl( wxDC *owner )
171 : wxX11DCImpl( owner )
172{
173 Init();
83df96d6
JS
174}
175
2b77c3fc
RR
176wxWindowDCImpl::wxWindowDCImpl( wxDC* owner, wxWindow *window )
177 : wxX11DCImpl( owner )
83df96d6 178{
3cd0b8c5
RR
179 wxASSERT_MSG( window, wxT("DC needs a window") );
180
5c9d9745
VZ
181 Init();
182
83df96d6 183 m_font = window->GetFont();
83df96d6 184
2b77c3fc 185 m_x11window = (WXWindow*) window->GetMainWindow();
83df96d6 186
3cd0b8c5 187 // not realized ?
2b77c3fc 188 if (!m_x11window)
3cd0b8c5
RR
189 {
190 // don't report problems
ab9d0a8c 191 m_ok = true;
3cd0b8c5
RR
192
193 return;
194 }
83df96d6 195
3cd0b8c5 196 m_display = (WXDisplay *) wxGlobalDisplay();
ab9d0a8c 197
2b5f62a0 198#if wxUSE_UNICODE
2b5f62a0
VZ
199 m_fontdesc = window->GetFont().GetNativeFontInfo()->description;
200#endif
201
3cd0b8c5
RR
202 int screen = DefaultScreen( (Display*) m_display );
203 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
83df96d6 204
3cd0b8c5 205 SetUpDC();
83df96d6 206
3cd0b8c5
RR
207 /* this must be done after SetUpDC, bacause SetUpDC calls the
208 repective SetBrush, SetPen, SetBackground etc functions
2b77c3fc 209 to set up the DC. SetBackground call m_window->SetBackground
3cd0b8c5
RR
210 and this might not be desired as the standard dc background
211 is white whereas a window might assume gray to be the
212 standard (as e.g. wxStatusBar) */
83df96d6 213
2b77c3fc 214 m_window = window;
83df96d6
JS
215}
216
2b77c3fc 217wxWindowDCImpl::~wxWindowDCImpl()
83df96d6 218{
3cd0b8c5
RR
219 Destroy();
220}
221
2b77c3fc
RR
222void wxWindowDCImpl::Init()
223{
224 m_display = (WXDisplay *) NULL;
225 m_penGC = (WXGC *) NULL;
226 m_brushGC = (WXGC *) NULL;
227 m_textGC = (WXGC *) NULL;
228 m_bgGC = (WXGC *) NULL;
229 m_cmap = (WXColormap *) NULL;
230 m_isMemDC = false;
231 m_isScreenDC = false;
232 m_x11window = (WXWindow*) NULL;
233
234#if wxUSE_UNICODE
235 m_context = wxTheApp->GetPangoContext();
236 m_fontdesc = (PangoFontDescription *)NULL;
237#endif
238}
239
240void wxWindowDCImpl::SetUpDC()
3cd0b8c5 241{
ab9d0a8c 242 m_ok = true;
3cd0b8c5
RR
243
244 wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
245
2b77c3fc
RR
246 bool ismono = false;
247 if (m_isMemDC)
248 {
249 wxMemoryDCImpl *mem_impl = (wxMemoryDCImpl *) this;
250 if (mem_impl->GetSelectedBitmap().IsOk())
251 ismono = mem_impl->GetSelectedBitmap().GetDepth() == 1;
252 }
253
3cd0b8c5
RR
254 if (m_isScreenDC)
255 {
2b77c3fc
RR
256 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxPEN_SCREEN );
257 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBRUSH_SCREEN );
258 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxTEXT_SCREEN );
259 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBG_SCREEN );
3cd0b8c5 260 }
3cd0b8c5 261 else
2b77c3fc 262 if (m_isMemDC && ismono)
3cd0b8c5 263 {
2b77c3fc
RR
264 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxPEN_MONO );
265 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBRUSH_MONO );
266 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxTEXT_MONO );
267 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBG_MONO );
3cd0b8c5 268 }
3cd0b8c5 269 else
83df96d6 270 {
2b77c3fc
RR
271 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxPEN_COLOUR );
272 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBRUSH_COLOUR );
273 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxTEXT_COLOUR );
274 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_x11window, wxBG_COLOUR );
83df96d6
JS
275 }
276
3cd0b8c5
RR
277 /* background colour */
278 m_backgroundBrush = *wxWHITE_BRUSH;
279 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
280 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel();
281
6033bbc1
JS
282 m_textForegroundColour = *wxBLACK;
283 m_textBackgroundColour = *wxWHITE;
284
3cd0b8c5
RR
285 /* m_textGC */
286 m_textForegroundColour.CalcPixel( m_cmap );
287 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
288
289 m_textBackgroundColour.CalcPixel( m_cmap );
290 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
291
292 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid );
293
0b5c0e1a
JS
294#if wxUSE_NANOX
295 // By default, draw transparently
296 GrSetGCUseBackground((GC) m_textGC, FALSE);
297#endif
298
3cd0b8c5
RR
299 /* m_penGC */
300 m_pen.GetColour().CalcPixel( m_cmap );
301 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
302 XSetBackground( (Display*) m_display, (GC) m_penGC, bg_col );
303
304 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, 0, LineSolid, CapNotLast, JoinRound );
305
306 /* m_brushGC */
307 m_brush.GetColour().CalcPixel( m_cmap );
308 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
309 XSetBackground( (Display*) m_display, (GC) m_brushGC, bg_col );
310
311 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
312
313 /* m_bgGC */
314 XSetForeground( (Display*) m_display, (GC) m_bgGC, bg_col );
315 XSetBackground( (Display*) m_display, (GC) m_bgGC, bg_col );
ab9d0a8c 316
3cd0b8c5
RR
317 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
318
319 /* ROPs */
320 XSetFunction( (Display*) m_display, (GC) m_textGC, GXcopy );
321 XSetFunction( (Display*) m_display, (GC) m_brushGC, GXcopy );
322 XSetFunction( (Display*) m_display, (GC)m_penGC, GXcopy );
323
324 /* clipping */
325 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
326 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
327 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
328 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
83df96d6 329
3cd0b8c5
RR
330 if (!hatch_bitmap)
331 {
1180fb81
RR
332 int xscreen = DefaultScreen( (Display*) m_display );
333 Window xroot = RootWindow( (Display*) m_display, xscreen );
ab9d0a8c 334
3cd0b8c5 335 hatch_bitmap = hatches;
1180fb81
RR
336 hatch_bitmap[0] = XCreateBitmapFromData( (Display*) m_display, xroot, bdiag_bits, bdiag_width, bdiag_height );
337 hatch_bitmap[1] = XCreateBitmapFromData( (Display*) m_display, xroot, cdiag_bits, cdiag_width, cdiag_height );
338 hatch_bitmap[2] = XCreateBitmapFromData( (Display*) m_display, xroot, fdiag_bits, fdiag_width, fdiag_height );
339 hatch_bitmap[3] = XCreateBitmapFromData( (Display*) m_display, xroot, cross_bits, cross_width, cross_height );
340 hatch_bitmap[4] = XCreateBitmapFromData( (Display*) m_display, xroot, horiz_bits, horiz_width, horiz_height );
341 hatch_bitmap[5] = XCreateBitmapFromData( (Display*) m_display, xroot, verti_bits, verti_width, verti_height );
3cd0b8c5
RR
342 }
343}
83df96d6 344
2b77c3fc 345void wxWindowDCImpl::DoGetSize( int* width, int* height ) const
3cd0b8c5 346{
2b77c3fc 347 wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") );
83df96d6 348
2b77c3fc 349 m_window->GetSize(width, height);
83df96d6
JS
350}
351
ab9d0a8c 352extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
3a0a5ada 353 const wxColour & col, int style);
b1699cd3 354
2b77c3fc 355bool wxWindowDCImpl::DoFloodFill(wxCoord x, wxCoord y,
3a0a5ada
VS
356 const wxColour& col, int style)
357{
2b77c3fc 358 return wxDoFloodFill(GetOwner(), x, y, col, style);
83df96d6
JS
359}
360
2b77c3fc 361bool wxWindowDCImpl::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
83df96d6
JS
362{
363 // Generic (and therefore rather inefficient) method.
364 // Could be improved.
365 wxMemoryDC memdc;
366 wxBitmap bitmap(1, 1);
367 memdc.SelectObject(bitmap);
2b77c3fc 368 memdc.Blit(0, 0, 1, 1, GetOwner(), x1, y1);
83df96d6 369 memdc.SelectObject(wxNullBitmap);
2b5f62a0 370 wxImage image(bitmap.ConvertToImage());
83df96d6 371 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
ab9d0a8c 372 return true;
83df96d6
JS
373}
374
2b77c3fc 375void wxWindowDCImpl::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
83df96d6 376{
2b77c3fc 377 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 378
3cd0b8c5
RR
379 if (m_pen.GetStyle() != wxTRANSPARENT)
380 {
2b77c3fc 381 if (m_x11window)
2b5f62a0
VZ
382 {
383 // This hack is for the iPaq: XDrawLine draws
384 // nothing, whereas XDrawLines works...
385 wxPoint points[2];
386 points[0].x = x1;
387 points[0].y = y1;
388 points[1].x = x2;
389 points[1].y = y2;
2b77c3fc 390 DoDrawLines( 2, points, 0, 0 );
ab9d0a8c 391
2b77c3fc 392 // XDrawLine( (Display*) m_display, (Window) m_x11window,
2b5f62a0
VZ
393 // (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
394 }
83df96d6 395
3cd0b8c5
RR
396 CalcBoundingBox(x1, y1);
397 CalcBoundingBox(x2, y2);
398 }
83df96d6
JS
399}
400
2b77c3fc 401void wxWindowDCImpl::DoCrossHair( wxCoord x, wxCoord y )
83df96d6 402{
2b77c3fc 403 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 404
3cd0b8c5
RR
405 if (m_pen.GetStyle() != wxTRANSPARENT)
406 {
407 int w = 0;
408 int h = 0;
2b77c3fc 409 DoGetSize( &w, &h );
3cd0b8c5
RR
410 wxCoord xx = XLOG2DEV(x);
411 wxCoord yy = YLOG2DEV(y);
2b77c3fc 412 if (m_x11window)
3cd0b8c5 413 {
2b77c3fc 414 XDrawLine( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 415 (GC) m_penGC, 0, yy, XLOG2DEVREL(w), yy );
2b77c3fc 416 XDrawLine( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
417 (GC) m_penGC, xx, 0, xx, YLOG2DEVREL(h) );
418 }
419 }
83df96d6
JS
420}
421
2b77c3fc 422void wxWindowDCImpl::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
83df96d6 423{
2b77c3fc 424 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
3cd0b8c5
RR
425
426 wxCoord xx1 = XLOG2DEV(x1);
427 wxCoord yy1 = YLOG2DEV(y1);
428 wxCoord xx2 = XLOG2DEV(x2);
429 wxCoord yy2 = YLOG2DEV(y2);
430 wxCoord xxc = XLOG2DEV(xc);
431 wxCoord yyc = YLOG2DEV(yc);
432 double dx = xx1 - xxc;
433 double dy = yy1 - yyc;
434 double radius = sqrt((double)(dx*dx+dy*dy));
435 wxCoord r = (wxCoord)radius;
83df96d6
JS
436 double radius1, radius2;
437
438 if (xx1 == xx2 && yy1 == yy2)
439 {
440 radius1 = 0.0;
441 radius2 = 360.0;
442 }
83df96d6 443 else
3cd0b8c5 444 if (radius == 0.0)
83df96d6 445 {
3cd0b8c5 446 radius1 = radius2 = 0.0;
83df96d6 447 }
3cd0b8c5 448 else
83df96d6 449 {
3cd0b8c5
RR
450 radius1 = (xx1 - xxc == 0) ?
451 (yy1 - yyc < 0) ? 90.0 : -90.0 :
452 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
453 radius2 = (xx2 - xxc == 0) ?
454 (yy2 - yyc < 0) ? 90.0 : -90.0 :
455 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
83df96d6 456 }
3cd0b8c5
RR
457 wxCoord alpha1 = wxCoord(radius1 * 64.0);
458 wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0);
459 while (alpha2 <= 0) alpha2 += 360*64;
460 while (alpha1 > 360*64) alpha1 -= 360*64;
83df96d6 461
2b77c3fc 462 if (m_x11window)
83df96d6 463 {
3cd0b8c5
RR
464 if (m_brush.GetStyle() != wxTRANSPARENT)
465 {
466 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
467 {
468 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
469 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
470 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 471
2b77c3fc 472 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 473 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
ab9d0a8c 474
3cd0b8c5
RR
475 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
476 } else
477 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
478 {
479 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
480 m_deviceOriginX % 15, m_deviceOriginY % 15 );
ab9d0a8c 481
2b77c3fc 482 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 483 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
ab9d0a8c 484
3cd0b8c5
RR
485 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
486 } else
487 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
488 {
489 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
490 m_deviceOriginX % 16, m_deviceOriginY % 16 );
ab9d0a8c 491
2b77c3fc 492 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 493 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
ab9d0a8c 494
3cd0b8c5
RR
495 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
496 } else
497 if (m_brush.GetStyle() == wxSTIPPLE)
498 {
499 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
500 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
501 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 502
2b77c3fc 503 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 504 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
ab9d0a8c 505
3cd0b8c5
RR
506 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
507 }
508 else
509 {
2b77c3fc 510 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
511 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
512 }
513 }
514
515 if (m_pen.GetStyle() != wxTRANSPARENT)
516 {
2b77c3fc 517 XDrawArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 518 (GC) m_penGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
ab9d0a8c 519
2b77c3fc 520 XDrawLine( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 521 (GC) m_penGC, xx1, yy1, xxc, yyc );
ab9d0a8c 522
2b77c3fc 523 XDrawLine( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
524 (GC) m_penGC, xxc, yyc, xx2, yy2 );
525 }
83df96d6 526 }
3cd0b8c5 527
83df96d6
JS
528 CalcBoundingBox (x1, y1);
529 CalcBoundingBox (x2, y2);
530}
531
2b77c3fc 532void wxWindowDCImpl::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
83df96d6 533{
2b77c3fc 534 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 535
3cd0b8c5
RR
536 wxCoord xx = XLOG2DEV(x);
537 wxCoord yy = YLOG2DEV(y);
538 wxCoord ww = m_signX * XLOG2DEVREL(width);
539 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 540
3cd0b8c5
RR
541 // CMB: handle -ve width and/or height
542 if (ww < 0) { ww = -ww; xx = xx - ww; }
543 if (hh < 0) { hh = -hh; yy = yy - hh; }
83df96d6 544
2b77c3fc 545 if (m_x11window)
83df96d6 546 {
3cd0b8c5
RR
547 wxCoord start = wxCoord(sa * 64.0);
548 wxCoord end = wxCoord((ea-sa) * 64.0);
83df96d6 549
3cd0b8c5
RR
550 if (m_brush.GetStyle() != wxTRANSPARENT)
551 {
552 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
553 {
554 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
555 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
556 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 557
2b77c3fc 558 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 559 (GC) m_textGC, xx, yy, ww, hh, start, end );
ab9d0a8c 560
3cd0b8c5
RR
561 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
562 } else
563 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
564 {
565 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
566 m_deviceOriginX % 15, m_deviceOriginY % 15 );
ab9d0a8c 567
2b77c3fc 568 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 569 (GC) m_brushGC, xx, yy, ww, hh, start, end );
ab9d0a8c 570
3cd0b8c5
RR
571 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
572 } else
573 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
574 {
575 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
576 m_deviceOriginX % 16, m_deviceOriginY % 16 );
ab9d0a8c 577
2b77c3fc 578 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 579 (GC) m_brushGC, xx, yy, ww, hh, start, end );
ab9d0a8c 580
3cd0b8c5
RR
581 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
582 } else
583 if (m_brush.GetStyle() == wxSTIPPLE)
584 {
585 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
586 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
587 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 588
2b77c3fc 589 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 590 (GC) m_brushGC, xx, yy, ww, hh, start, end );
ab9d0a8c 591
3cd0b8c5
RR
592 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
593 }
594 else
595 {
2b77c3fc 596 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
597 (GC) m_brushGC, xx, yy, ww, hh, start, end );
598 }
599 }
83df96d6 600
3cd0b8c5
RR
601 if (m_pen.GetStyle() != wxTRANSPARENT)
602 {
2b77c3fc 603 XDrawArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
604 (GC) m_penGC, xx, yy, ww, hh, start, end );
605 }
83df96d6 606 }
3cd0b8c5 607
83df96d6
JS
608 CalcBoundingBox (x, y);
609 CalcBoundingBox (x + width, y + height);
610}
611
2b77c3fc 612void wxWindowDCImpl::DoDrawPoint( wxCoord x, wxCoord y )
83df96d6 613{
2b77c3fc 614 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 615
2b77c3fc
RR
616 if ((m_pen.GetStyle() != wxTRANSPARENT) && m_x11window)
617 XDrawPoint( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 618 (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
83df96d6 619
83df96d6
JS
620 CalcBoundingBox (x, y);
621}
622
2b77c3fc 623void wxWindowDCImpl::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
83df96d6 624{
2b77c3fc 625 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 626
3cd0b8c5
RR
627 if (m_pen.GetStyle() == wxTRANSPARENT) return;
628 if (n <= 0) return;
83df96d6 629
3cd0b8c5
RR
630 XPoint *xpoints = new XPoint[n];
631 for (int i = 0; i < n; i++)
83df96d6 632 {
3cd0b8c5
RR
633 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
634 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
ab9d0a8c 635
3cd0b8c5 636 CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset );
83df96d6 637 }
2b77c3fc 638 XDrawLines( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xpoints, n, 0 );
3cd0b8c5
RR
639
640 delete[] xpoints;
83df96d6
JS
641}
642
2b77c3fc 643void wxWindowDCImpl::DoDrawPolygon( int n, wxPoint points[],
89954433
VZ
644 wxCoord xoffset, wxCoord yoffset,
645 int WXUNUSED(fillStyle) )
83df96d6 646{
2b77c3fc 647 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 648
3cd0b8c5 649 if (n <= 0) return;
83df96d6 650
3cd0b8c5 651 XPoint *xpoints = new XPoint[n + 1];
83df96d6
JS
652 int i;
653 for (i = 0; i < n; i++)
654 {
3cd0b8c5
RR
655 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
656 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
ab9d0a8c 657
83df96d6
JS
658 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
659 }
660
2b77c3fc 661 if (m_x11window)
83df96d6 662 {
3cd0b8c5
RR
663 if (m_brush.GetStyle() != wxTRANSPARENT)
664 {
ab9d0a8c 665
3cd0b8c5
RR
666 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
667 {
668 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
669 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
670 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 671
2b77c3fc 672 XFillPolygon( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 673 (GC) m_textGC, xpoints, n, Complex, 0);
ab9d0a8c 674
3cd0b8c5
RR
675 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
676 } else
677 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
678 {
679 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
680 m_deviceOriginX % 15, m_deviceOriginY % 15 );
ab9d0a8c 681
2b77c3fc 682 XFillPolygon( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 683 (GC) m_brushGC, xpoints, n, Complex, 0);
ab9d0a8c 684
3cd0b8c5
RR
685 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
686 } else
687 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
688 {
689 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
690 m_deviceOriginX % 16, m_deviceOriginY % 16 );
ab9d0a8c 691
2b77c3fc 692 XFillPolygon( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 693 (GC) m_brushGC, xpoints, n, Complex, 0);
ab9d0a8c 694
3cd0b8c5
RR
695 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
696 } else
697 if (m_brush.GetStyle() == wxSTIPPLE)
698 {
699 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
700 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
701 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 702
2b77c3fc 703 XFillPolygon( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 704 (GC) m_brushGC, xpoints, n, Complex, 0);
ab9d0a8c 705
3cd0b8c5
RR
706 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
707 }
708 else
709 {
2b77c3fc 710 XFillPolygon( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
711 (GC) m_brushGC, xpoints, n, Complex, 0);
712 }
713 }
83df96d6 714
3cd0b8c5
RR
715 if (m_pen.GetStyle () != wxTRANSPARENT)
716 {
717 // Close figure for XDrawLines
718 xpoints[i].x = xpoints[0].x;
719 xpoints[i].y = xpoints[0].y;
720
2b77c3fc 721 XDrawLines( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xpoints, n + 1, 0);
3cd0b8c5 722 }
83df96d6
JS
723 }
724
3cd0b8c5 725 delete[] xpoints;
83df96d6
JS
726}
727
2b77c3fc 728void wxWindowDCImpl::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 729{
2b77c3fc 730 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 731
3cd0b8c5
RR
732 wxCoord xx = XLOG2DEV(x);
733 wxCoord yy = YLOG2DEV(y);
734 wxCoord ww = m_signX * XLOG2DEVREL(width);
735 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 736
3cd0b8c5
RR
737 // CMB: draw nothing if transformed w or h is 0
738 if (ww == 0 || hh == 0) return;
83df96d6 739
3cd0b8c5
RR
740 // CMB: handle -ve width and/or height
741 if (ww < 0) { ww = -ww; xx = xx - ww; }
742 if (hh < 0) { hh = -hh; yy = yy - hh; }
ab9d0a8c 743
2b77c3fc 744 if (m_x11window)
83df96d6 745 {
3cd0b8c5
RR
746 if (m_brush.GetStyle() != wxTRANSPARENT)
747 {
748 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
749 {
750 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
751 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
752 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 753
2b77c3fc 754 XFillRectangle( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 755 (GC) m_textGC, xx, yy, ww, hh );
ab9d0a8c 756
3cd0b8c5
RR
757 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
758 } else
759 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
760 {
761 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
762 m_deviceOriginX % 15, m_deviceOriginY % 15 );
ab9d0a8c 763
2b77c3fc 764 XFillRectangle( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 765 (GC) m_brushGC, xx, yy, ww, hh );
ab9d0a8c 766
3cd0b8c5
RR
767 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
768 } else
769 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
770 {
771 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
772 m_deviceOriginX % 16, m_deviceOriginY % 16 );
ab9d0a8c 773
2b77c3fc 774 XFillRectangle( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 775 (GC) m_brushGC, xx, yy, ww, hh );
ab9d0a8c 776
3cd0b8c5
RR
777 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
778 } else
779 if (m_brush.GetStyle() == wxSTIPPLE)
780 {
781 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
782 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
783 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 784
2b77c3fc 785 XFillRectangle( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 786 (GC) m_brushGC, xx, yy, ww, hh );
ab9d0a8c 787
3cd0b8c5
RR
788 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
789 }
790 else
791 {
2b77c3fc 792 XFillRectangle( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
793 (GC) m_brushGC, xx, yy, ww, hh );
794 }
795 }
83df96d6 796
3cd0b8c5
RR
797 if (m_pen.GetStyle () != wxTRANSPARENT)
798 {
2b77c3fc 799 XDrawRectangle( (Display*) m_display, (Window) m_x11window,
887dd52f 800 (GC) m_penGC, xx, yy, ww-1, hh-1 );
3cd0b8c5 801 }
83df96d6 802 }
3cd0b8c5
RR
803
804 CalcBoundingBox( x, y );
805 CalcBoundingBox( x + width, y + height );
83df96d6
JS
806}
807
2b77c3fc 808void wxWindowDCImpl::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
83df96d6 809{
2b77c3fc 810 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
ab9d0a8c 811
e8ba218b 812 if (radius < 0.0) radius = - radius * ((width < height) ? width : height);
ab9d0a8c 813
e8ba218b
VZ
814 wxCoord xx = XLOG2DEV(x);
815 wxCoord yy = YLOG2DEV(y);
816 wxCoord ww = m_signX * XLOG2DEVREL(width);
817 wxCoord hh = m_signY * YLOG2DEVREL(height);
818 wxCoord rr = XLOG2DEVREL((wxCoord)radius);
ab9d0a8c 819
e8ba218b
VZ
820 // CMB: handle -ve width and/or height
821 if (ww < 0) { ww = -ww; xx = xx - ww; }
822 if (hh < 0) { hh = -hh; yy = yy - hh; }
ab9d0a8c 823
e8ba218b
VZ
824 // CMB: if radius is zero use DrawRectangle() instead to avoid
825 // X drawing errors with small radii
826 if (rr == 0)
827 {
2b77c3fc 828 XDrawRectangle( (Display*) m_display, (Window) m_x11window,
e8ba218b
VZ
829 (GC) m_penGC, x, y, width, height);
830 return;
831 }
ab9d0a8c 832
e8ba218b
VZ
833 // CMB: draw nothing if transformed w or h is 0
834 if (ww == 0 || hh == 0) return;
ab9d0a8c 835
e8ba218b
VZ
836 // CMB: adjust size if outline is drawn otherwise the result is
837 // 1 pixel too wide and high
838 if (m_pen.GetStyle() != wxTRANSPARENT)
839 {
840 ww--;
841 hh--;
842 }
ab9d0a8c 843
2b77c3fc 844 if (m_x11window)
e8ba218b
VZ
845 {
846 // CMB: ensure dd is not larger than rectangle otherwise we
847 // get an hour glass shape
848 wxCoord dd = 2 * rr;
849 if (dd > ww) dd = ww;
850 if (dd > hh) dd = hh;
851 rr = dd / 2;
ab9d0a8c 852
e8ba218b
VZ
853 if (m_brush.GetStyle() != wxTRANSPARENT)
854 {
855 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
856 {
ab9d0a8c
WS
857 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
858 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
e8ba218b 859 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
2b77c3fc
RR
860 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx+rr, yy, ww-dd+1, hh );
861 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx, yy+rr, ww, hh-dd+1 );
862 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx, yy, dd, dd, 90*64, 90*64 );
863 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx+ww-dd, yy, dd, dd, 0, 90*64 );
864 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
865 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_textGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
e8ba218b
VZ
866 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0);
867 } else
868 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
869 {
870 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 );
2b77c3fc
RR
871 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh );
872 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 );
873 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 );
874 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 );
875 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
876 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
e8ba218b
VZ
877 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0);
878 } else
879 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
880 {
881 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 );
2b77c3fc
RR
882 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh );
883 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 );
884 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 );
885 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 );
886 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
887 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
e8ba218b
VZ
888 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0);
889 } else
890 if (m_brush.GetStyle() == wxSTIPPLE)
891 {
ab9d0a8c 892 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
e8ba218b
VZ
893 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
894 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
2b77c3fc
RR
895 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh );
896 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 );
897 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 );
898 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 );
899 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
900 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
e8ba218b
VZ
901 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0);
902 }
903 else
904 {
2b77c3fc
RR
905 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+rr, yy, ww-dd+1, hh );
906 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+rr, ww, hh-dd+1 );
907 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy, dd, dd, 90*64, 90*64 );
908 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy, dd, dd, 0, 90*64 );
909 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
910 XFillArc( (Display*) m_display, (Window) m_x11window, (GC) m_brushGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
e8ba218b
VZ
911 }
912 }
913 if (m_pen.GetStyle() != wxTRANSPARENT)
914 {
2b77c3fc
RR
915 XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+rr+1, yy, xx+ww-rr, yy );
916 XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+rr+1, yy+hh, xx+ww-rr, yy+hh );
917 XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx, yy+rr+1, xx, yy+hh-rr );
918 XDrawLine( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+ww, yy+rr+1, xx+ww, yy+hh-rr );
919 XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx, yy, dd, dd, 90*64, 90*64 );
920 XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+ww-dd, yy, dd, dd, 0, 90*64 );
921 XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
922 XDrawArc( (Display*) m_display, (Window) m_x11window, (GC) m_penGC, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
e8ba218b
VZ
923 }
924 }
ab9d0a8c 925
e8ba218b
VZ
926 // this ignores the radius
927 CalcBoundingBox( x, y );
928 CalcBoundingBox( x + width, y + height );
3cd0b8c5 929}
83df96d6 930
2b77c3fc 931void wxWindowDCImpl::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
3cd0b8c5 932{
2b77c3fc 933 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 934
3cd0b8c5
RR
935 wxCoord xx = XLOG2DEV(x);
936 wxCoord yy = YLOG2DEV(y);
937 wxCoord ww = m_signX * XLOG2DEVREL(width);
938 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 939
3cd0b8c5
RR
940 // CMB: handle -ve width and/or height
941 if (ww < 0) { ww = -ww; xx = xx - ww; }
942 if (hh < 0) { hh = -hh; yy = yy - hh; }
83df96d6 943
2b77c3fc 944 if (m_x11window)
83df96d6 945 {
3cd0b8c5
RR
946 if (m_brush.GetStyle() != wxTRANSPARENT)
947 {
948 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
949 {
950 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
951 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
952 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 953
2b77c3fc 954 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 955 (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 );
ab9d0a8c 956
3cd0b8c5
RR
957 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
958 } else
959 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
960 {
961 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
962 m_deviceOriginX % 15, m_deviceOriginY % 15 );
ab9d0a8c 963
2b77c3fc 964 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 965 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
ab9d0a8c 966
3cd0b8c5
RR
967 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
968 } else
969 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
970 {
971 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
972 m_deviceOriginX % 16, m_deviceOriginY % 16 );
ab9d0a8c 973
2b77c3fc 974 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 975 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
ab9d0a8c 976
3cd0b8c5
RR
977 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
978 } else
979 if (m_brush.GetStyle() == wxSTIPPLE)
980 {
981 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
982 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
983 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
ab9d0a8c 984
2b77c3fc 985 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5 986 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
ab9d0a8c 987
3cd0b8c5
RR
988 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
989 }
990 else
991 {
2b77c3fc 992 XFillArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
993 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
994 }
995 }
83df96d6 996
3cd0b8c5
RR
997 if (m_pen.GetStyle () != wxTRANSPARENT)
998 {
2b77c3fc 999 XDrawArc( (Display*) m_display, (Window) m_x11window,
3cd0b8c5
RR
1000 (GC) m_penGC, xx, yy, ww, hh, 0, 360*64 );
1001 }
83df96d6 1002 }
83df96d6 1003
3cd0b8c5
RR
1004 CalcBoundingBox( x, y );
1005 CalcBoundingBox( x + width, y + height );
1006}
83df96d6 1007
2b77c3fc 1008void wxWindowDCImpl::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
3cd0b8c5 1009{
ab9d0a8c 1010 DoDrawBitmap(icon, x, y, true);
83df96d6
JS
1011}
1012
c978d361 1013#if wxUSE_NANOX
2b77c3fc 1014void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap,
c978d361
JS
1015 wxCoord x, wxCoord y,
1016 bool useMask )
1017{
2b77c3fc 1018 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
c978d361 1019
2b77c3fc 1020 wxCHECK_RET( bitmap.IsOk(), wxT("invalid bitmap") );
ab9d0a8c 1021
c978d361
JS
1022 bool is_mono = (bitmap.GetBitmap() != NULL);
1023
1024 /* scale/translate size and position */
1025 int xx = XLOG2DEV(x);
1026 int yy = YLOG2DEV(y);
1027
1028 int w = bitmap.GetWidth();
1029 int h = bitmap.GetHeight();
1030
1031 CalcBoundingBox( x, y );
1032 CalcBoundingBox( x + w, y + h );
1033
2b77c3fc 1034 if (!m_x11window) return;
c978d361
JS
1035
1036 int ww = XLOG2DEVREL(w);
1037 int hh = YLOG2DEVREL(h);
1038
1039 /* compare to current clipping region */
1040 if (!m_currentClippingRegion.IsNull())
1041 {
1042 wxRegion tmp( xx,yy,ww,hh );
1043 tmp.Intersect( m_currentClippingRegion );
1044 if (tmp.IsEmpty())
1045 return;
1046 }
1047
1048 /* scale bitmap if required */
1049 wxBitmap use_bitmap;
1050 if ((w != ww) || (h != hh))
1051 {
2b5f62a0 1052 wxImage image( bitmap.ConvertToImage() );
c978d361
JS
1053 image.Rescale( ww, hh );
1054#if 0
1055 if (is_mono)
1056 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1057 else
1058#endif
2b5f62a0 1059 use_bitmap = image;
c978d361
JS
1060 }
1061 else
1062 {
1063 use_bitmap = bitmap;
1064 }
1065
1066 /* apply mask if any */
1067 WXPixmap mask = NULL;
1068 if (use_bitmap.GetMask())
1069 mask = use_bitmap.GetMask()->GetBitmap();
1070
1071 if (useMask && mask)
1072 {
1073 Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ;
1074 Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ;
1075 Pixmap bufPixmap = GrNewPixmap(w, h, 0);
1076 GC gc = GrNewGC();
1077 GrSetGCUseBackground(gc, FALSE);
1078 GrSetGCMode(gc, GR_MODE_COPY);
1079
1080 // This code assumes that background and foreground
1081 // colours are used in ROPs, like in MSW.
1082 // Not sure if this is true.
1083
1084 // Copy destination to buffer.
1085 // In DoBlit, we need this step because Blit has
1086 // a ROP argument. Here, we don't need it.
1087 // In DoBlit, we may be able to eliminate this step
1088 // if we check if the rop = copy
1089#if 0
2b77c3fc 1090 GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_x11window,
c978d361
JS
1091 0, 0, GR_MODE_COPY);
1092#endif
ab9d0a8c 1093
c978d361
JS
1094 // Copy src to buffer using selected raster op (none selected
1095 // in DrawBitmap, so just use Gxcopy)
1096 GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap,
1097 0, 0, GR_MODE_COPY);
1098
1099 // Set masked area in buffer to BLACK (pixel value 0)
1100 GrSetGCBackground(gc, WHITE);
1101 GrSetGCForeground(gc, BLACK);
1102 GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap,
1103 0, 0, GR_MODE_AND);
ab9d0a8c 1104
c978d361
JS
1105 // set unmasked area in dest to BLACK
1106 GrSetGCBackground(gc, BLACK);
1107 GrSetGCForeground(gc, WHITE);
2b77c3fc 1108 GrCopyArea((Window) m_x11window, gc, xx, yy, w, h, maskPixmap,
c978d361
JS
1109 0, 0, GR_MODE_AND);
1110
1111 // OR buffer to dest
2b77c3fc 1112 GrCopyArea((Window) m_x11window, gc, xx, yy, w, h, bufPixmap,
c978d361
JS
1113 0, 0, GR_MODE_OR);
1114
1115 GrDestroyGC(gc);
1116 GrDestroyWindow(bufPixmap);
1117 }
1118 else
2b77c3fc 1119 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_x11window,
c978d361
JS
1120 (GC) m_penGC, 0, 0, w, h, xx, yy );
1121
1122 /* remove mask again if any */
1123 if (useMask && mask)
1124 {
1125 if (!m_currentClippingRegion.IsNull())
1126 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1127 }
1128}
1129
1130#else
1131
1132// Normal X11
2b77c3fc 1133void wxWindowDCImpl::DoDrawBitmap( const wxBitmap &bitmap,
3cd0b8c5
RR
1134 wxCoord x, wxCoord y,
1135 bool useMask )
83df96d6 1136{
2b77c3fc 1137 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1138
2b77c3fc 1139 wxCHECK_RET( bitmap.IsOk(), wxT("invalid bitmap") );
ab9d0a8c 1140
3cd0b8c5 1141 bool is_mono = (bitmap.GetBitmap() != NULL);
83df96d6 1142
b1633d20 1143 // scale/translate size and position
3cd0b8c5
RR
1144 int xx = XLOG2DEV(x);
1145 int yy = YLOG2DEV(y);
83df96d6 1146
3cd0b8c5
RR
1147 int w = bitmap.GetWidth();
1148 int h = bitmap.GetHeight();
83df96d6 1149
3cd0b8c5
RR
1150 CalcBoundingBox( x, y );
1151 CalcBoundingBox( x + w, y + h );
83df96d6 1152
2b77c3fc 1153 if (!m_x11window) return;
83df96d6 1154
3cd0b8c5
RR
1155 int ww = XLOG2DEVREL(w);
1156 int hh = YLOG2DEVREL(h);
83df96d6 1157
b1633d20 1158 // compare to current clipping region
3cd0b8c5 1159 if (!m_currentClippingRegion.IsNull())
83df96d6 1160 {
3cd0b8c5
RR
1161 wxRegion tmp( xx,yy,ww,hh );
1162 tmp.Intersect( m_currentClippingRegion );
1163 if (tmp.IsEmpty())
1164 return;
83df96d6
JS
1165 }
1166
b1633d20 1167 // scale bitmap if required
3cd0b8c5
RR
1168 wxBitmap use_bitmap;
1169 if ((w != ww) || (h != hh))
83df96d6 1170 {
2b5f62a0 1171 wxImage image( bitmap.ConvertToImage() );
3cd0b8c5 1172 image.Rescale( ww, hh );
a11672a4 1173#if 0
3cd0b8c5
RR
1174 if (is_mono)
1175 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1176 else
a11672a4 1177#endif
2b5f62a0 1178 use_bitmap = image;
3cd0b8c5
RR
1179 }
1180 else
1181 {
1182 use_bitmap = bitmap;
83df96d6 1183 }
83df96d6 1184
b1633d20 1185 // apply mask if any
a11672a4 1186 WXPixmap mask = NULL;
3cd0b8c5 1187 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
ab9d0a8c 1188
2fb0cabb
JS
1189 bool setClipMask = false;
1190
1191 if (!m_currentClippingRegion.IsNull() || (useMask && mask))
1192 {
1193 // XSetClipMask() call is necessary (because of clip region and/or transparent mask)
1194 setClipMask = true;
1195 Pixmap new_pixmap = 0;
1196
1197 if (!m_currentClippingRegion.IsNull())
3cd0b8c5 1198 {
2fb0cabb
JS
1199 // clipping necessary => create new_pixmap
1200 Display *xdisplay = (Display*) m_display;
1201 int xscreen = DefaultScreen( xdisplay );
1202 Window xroot = RootWindow( xdisplay, xscreen );
1203
cc5fb8a7 1204 new_pixmap = XCreatePixmap( xdisplay, xroot, ww, hh, 1 );
2fb0cabb
JS
1205 GC gc = XCreateGC( xdisplay, new_pixmap, 0, NULL );
1206
4077791b 1207 XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) );
670f9935 1208
2fb0cabb 1209 XSetFillStyle( xdisplay, gc, FillSolid );
cc5fb8a7 1210 XFillRectangle( xdisplay, new_pixmap, gc, 0, 0, ww, hh );
2fb0cabb 1211
4077791b 1212 XSetForeground( xdisplay, gc, WhitePixel(xdisplay,xscreen) );
2fb0cabb
JS
1213
1214 if (useMask && mask)
3cd0b8c5 1215 {
2fb0cabb
JS
1216 // transparent mask => call XSetStipple
1217 XSetFillStyle( xdisplay, gc, FillStippled );
1218 XSetTSOrigin( xdisplay, gc, 0, 0);
1219 XSetStipple( xdisplay, gc, (Pixmap) mask);
3cd0b8c5 1220 }
ab9d0a8c 1221
2fb0cabb
JS
1222 wxCoord clip_x, clip_y, clip_w, clip_h;
1223 m_currentClippingRegion.GetBox(clip_x, clip_y, clip_w, clip_h);
1224 XFillRectangle( xdisplay, new_pixmap, gc, clip_x-xx, clip_y-yy, clip_w, clip_h );
1225
1226 XFreeGC( xdisplay, gc );
1227 }
1228
1229 if (is_mono)
1230 {
1231 if (new_pixmap)
1232 XSetClipMask( (Display*) m_display, (GC) m_textGC, new_pixmap );
1233 else
1234 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1235 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1236 }
1237 else
1238 {
1239 if (new_pixmap)
1240 XSetClipMask( (Display*) m_display, (GC) m_penGC, new_pixmap );
1241 else
1242 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1243 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
3cd0b8c5 1244 }
83df96d6 1245
2fb0cabb
JS
1246 if (new_pixmap)
1247 XFreePixmap( (Display*) m_display, new_pixmap );
1248 }
1249
b1633d20
RR
1250 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1251 // drawing a mono-bitmap (XBitmap) we use the current text GC
3cd0b8c5 1252 if (is_mono)
2b77c3fc 1253 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_x11window,
cc5fb8a7 1254 (GC) m_textGC, 0, 0, ww, hh, xx, yy, 1 );
3cd0b8c5 1255 else
2b77c3fc 1256 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_x11window,
cc5fb8a7 1257 (GC) m_penGC, 0, 0, ww, hh, xx, yy );
3cd0b8c5 1258
b1633d20 1259 // remove mask again if any
2fb0cabb 1260 if (setClipMask)
83df96d6 1261 {
3cd0b8c5 1262 if (is_mono)
83df96d6 1263 {
a11672a4
RR
1264 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1265 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 1266 if (!m_currentClippingRegion.IsNull())
a11672a4 1267 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1268 }
1269 else
1270 {
a11672a4
RR
1271 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1272 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 1273 if (!m_currentClippingRegion.IsNull())
a11672a4 1274 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6 1275 }
83df96d6 1276 }
83df96d6 1277}
c978d361
JS
1278#endif
1279 // wxUSE_NANOX/!wxUSE_NANOX
83df96d6 1280
2b77c3fc 1281bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
b1633d20 1282 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask,
83df96d6
JS
1283 wxCoord xsrcMask, wxCoord ysrcMask )
1284{
3cd0b8c5
RR
1285 /* this is the nth try to get this utterly useless function to
1286 work. it now completely ignores the scaling or translation
1287 of the source dc, but scales correctly on the target dc and
1288 knows about possible mask information in a memory dc. */
83df96d6 1289
2b77c3fc 1290 wxCHECK_MSG( IsOk(), false, wxT("invalid window dc") );
83df96d6 1291
ab9d0a8c 1292 wxCHECK_MSG( source, false, wxT("invalid source dc") );
83df96d6 1293
2b77c3fc 1294 if (!m_x11window) return false;
83df96d6 1295
3cd0b8c5 1296 // transform the source DC coords to the device ones
d3ae69de
VZ
1297 xsrc = source->LogicalToDeviceX(xsrc);
1298 ysrc = source->LogicalToDeviceY(ysrc);
83df96d6 1299
3cd0b8c5
RR
1300 wxClientDC *srcDC = (wxClientDC*)source;
1301 wxMemoryDC *memDC = (wxMemoryDC*)source;
2b77c3fc 1302 wxWindowDCImpl *src_impl = (wxWindowDCImpl*) srcDC->GetImpl();
83df96d6 1303
ab9d0a8c
WS
1304 bool use_bitmap_method = false;
1305 bool is_mono = false;
83df96d6 1306
ab9d0a8c 1307 // TODO: use the mask origin when drawing transparently
83df96d6
JS
1308 if (xsrcMask == -1 && ysrcMask == -1)
1309 {
b1633d20
RR
1310 xsrcMask = xsrc;
1311 ysrcMask = ysrc;
83df96d6 1312 }
ab9d0a8c 1313
2b77c3fc 1314 if (src_impl->m_isMemDC)
83df96d6 1315 {
2b77c3fc
RR
1316 wxBitmap selected = memDC->GetSelectedBitmap();
1317
1318 if (!selected.IsOk()) return false;
83df96d6 1319
3cd0b8c5
RR
1320 /* we use the "XCopyArea" way to copy a memory dc into
1321 y different window if the memory dc BOTH
1322 a) doesn't have any mask or its mask isn't used
1323 b) it is clipped
1324 c) is not 1-bit */
83df96d6 1325
2b77c3fc 1326 if (useMask && (selected.GetMask()))
83df96d6 1327 {
3cd0b8c5
RR
1328 /* we HAVE TO use the direct way for memory dcs
1329 that have mask since the XCopyArea doesn't know
1330 about masks */
ab9d0a8c 1331 use_bitmap_method = true;
3cd0b8c5 1332 }
2b77c3fc 1333 else if (selected.GetDepth() == 1)
3cd0b8c5
RR
1334 {
1335 /* we HAVE TO use the direct way for memory dcs
1336 that are bitmaps because XCopyArea doesn't cope
1337 with different bit depths */
ab9d0a8c
WS
1338 is_mono = true;
1339 use_bitmap_method = true;
3cd0b8c5
RR
1340 }
1341 else if ((xsrc == 0) && (ysrc == 0) &&
2b77c3fc
RR
1342 (width == selected.GetWidth()) &&
1343 (height == selected.GetHeight()))
3cd0b8c5
RR
1344 {
1345 /* we SHOULD use the direct way if all of the bitmap
1346 in the memory dc is copied in which case XCopyArea
1347 wouldn't be able able to boost performace by reducing
1348 the area to be scaled */
ab9d0a8c 1349 use_bitmap_method = true;
83df96d6
JS
1350 }
1351 else
1352 {
ab9d0a8c 1353 use_bitmap_method = false;
83df96d6
JS
1354 }
1355 }
83df96d6 1356
3cd0b8c5
RR
1357 CalcBoundingBox( xdest, ydest );
1358 CalcBoundingBox( xdest + width, ydest + height );
1359
b1633d20 1360 // scale/translate size and position
3cd0b8c5
RR
1361 wxCoord xx = XLOG2DEV(xdest);
1362 wxCoord yy = YLOG2DEV(ydest);
1363
1364 wxCoord ww = XLOG2DEVREL(width);
1365 wxCoord hh = YLOG2DEVREL(height);
1366
b1633d20 1367 // compare to current clipping region
3cd0b8c5 1368 if (!m_currentClippingRegion.IsNull())
83df96d6 1369 {
3cd0b8c5
RR
1370 wxRegion tmp( xx,yy,ww,hh );
1371 tmp.Intersect( m_currentClippingRegion );
1372 if (tmp.IsEmpty())
ab9d0a8c 1373 return true;
3cd0b8c5 1374 }
83df96d6 1375
3cd0b8c5
RR
1376 int old_logical_func = m_logicalFunction;
1377 SetLogicalFunction( logical_func );
83df96d6 1378
3cd0b8c5
RR
1379 if (use_bitmap_method)
1380 {
2b77c3fc
RR
1381 wxBitmap selected = memDC->GetSelectedBitmap();
1382
b1633d20 1383 // scale/translate bitmap size
2b77c3fc
RR
1384 wxCoord bm_width = selected.GetWidth();
1385 wxCoord bm_height = selected.GetHeight();
83df96d6 1386
3cd0b8c5
RR
1387 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1388 wxCoord bm_hh = YLOG2DEVREL( bm_height );
83df96d6 1389
b1633d20 1390 // scale bitmap if required
3cd0b8c5 1391 wxBitmap use_bitmap;
83df96d6 1392
3cd0b8c5
RR
1393 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1394 {
2b77c3fc 1395 wxImage image( selected.ConvertToImage() );
3cd0b8c5 1396 image = image.Scale( bm_ww, bm_hh );
83df96d6 1397
b1633d20 1398#if 0
3cd0b8c5
RR
1399 if (is_mono)
1400 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1401 else
b1633d20 1402#endif
2b5f62a0 1403 use_bitmap = image;
3cd0b8c5
RR
1404 }
1405 else
1406 {
2b77c3fc 1407 use_bitmap = selected;
3cd0b8c5
RR
1408 }
1409
b1633d20
RR
1410 // apply mask if any
1411 WXPixmap mask = NULL;
3cd0b8c5 1412 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
83df96d6 1413
3cd0b8c5 1414 if (useMask && mask)
83df96d6 1415 {
b1633d20
RR
1416 WXPixmap new_mask = NULL;
1417#if 0
3cd0b8c5 1418 if (!m_currentClippingRegion.IsNull())
83df96d6 1419 {
3cd0b8c5
RR
1420 GdkColor col;
1421 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1422 GdkGC *gc = gdk_gc_new( new_mask );
1423 col.pixel = 0;
1424 gdk_gc_set_foreground( gc, &col );
1425 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1426 col.pixel = 0;
1427 gdk_gc_set_background( gc, &col );
1428 col.pixel = 1;
1429 gdk_gc_set_foreground( gc, &col );
1430 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1431 gdk_gc_set_clip_origin( gc, -xx, -yy );
1432 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1433 gdk_gc_set_stipple( gc, mask );
1434 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1435 gdk_gc_unref( gc );
83df96d6 1436 }
b1633d20 1437#endif
3cd0b8c5 1438 if (is_mono)
83df96d6 1439 {
3cd0b8c5 1440 if (new_mask)
b1633d20 1441 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 1442 else
b1633d20
RR
1443 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1444 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
83df96d6
JS
1445 }
1446 else
1447 {
3cd0b8c5 1448 if (new_mask)
b1633d20 1449 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 1450 else
b1633d20
RR
1451 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1452 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
83df96d6 1453 }
ab9d0a8c 1454
3cd0b8c5 1455 if (new_mask)
b1633d20 1456 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 1457 }
83df96d6 1458
b1633d20
RR
1459 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1460 // drawing a mono-bitmap (XBitmap) we use the current text GC
83df96d6 1461
3cd0b8c5 1462 if (is_mono)
2b77c3fc 1463 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_x11window,
b1633d20 1464 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
83df96d6 1465 else
2b77c3fc 1466 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_x11window,
b1633d20 1467 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
83df96d6 1468
b1633d20 1469 // remove mask again if any
3cd0b8c5 1470 if (useMask && mask)
83df96d6 1471 {
3cd0b8c5
RR
1472 if (is_mono)
1473 {
b1633d20
RR
1474 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1475 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 1476 if (!m_currentClippingRegion.IsNull())
b1633d20 1477 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
3cd0b8c5
RR
1478 }
1479 else
83df96d6 1480 {
b1633d20
RR
1481 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1482 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 1483 if (!m_currentClippingRegion.IsNull())
b1633d20 1484 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1485 }
1486 }
83df96d6 1487 }
b1633d20 1488 else // use_bitmap_method
83df96d6 1489 {
3cd0b8c5 1490 if ((width != ww) || (height != hh))
83df96d6 1491 {
b1633d20 1492 /* Draw source window into a bitmap as we cannot scale
3cd0b8c5
RR
1493 a window in contrast to a bitmap. this would actually
1494 work with memory dcs as well, but we'd lose the mask
1495 information and waste one step in this process since
1496 a memory already has a bitmap. all this is slightly
1497 inefficient as we could take an XImage directly from
1498 an X window, but we'd then also have to care that
1499 the window is not outside the screen (in which case
1500 we'd get a BadMatch or what not).
1501 Is a double XGetImage and combined XGetPixel and
1502 XPutPixel really faster? I'm not sure. look at wxXt
1503 for a different implementation of the same problem. */
1504
1505 wxBitmap bitmap( width, height );
1506
b1633d20
RR
1507 // copy including child window contents
1508 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1509 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
1510 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1511 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1512
b1633d20 1513 // scale image
2b5f62a0 1514 wxImage image( bitmap.ConvertToImage() );
3cd0b8c5
RR
1515 image = image.Scale( ww, hh );
1516
b1633d20 1517 // convert to bitmap
2b5f62a0 1518 bitmap = image;
3cd0b8c5 1519
b1633d20 1520 // draw scaled bitmap
2b77c3fc 1521 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_x11window,
b1633d20 1522 (GC) m_penGC, 0, 0, width, height, xx, yy );
83df96d6
JS
1523 }
1524 else
3cd0b8c5 1525 {
b1633d20
RR
1526 // No scaling and not a memory dc with a mask either
1527
1528 // copy including child window contents
1529 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
2b77c3fc 1530 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_x11window,
b1633d20
RR
1531 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1532 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1533 }
83df96d6
JS
1534 }
1535
3cd0b8c5 1536 SetLogicalFunction( old_logical_func );
ab9d0a8c
WS
1537
1538 return true;
83df96d6
JS
1539}
1540
2b77c3fc 1541void wxWindowDCImpl::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
83df96d6 1542{
2b77c3fc 1543 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1544
2b77c3fc 1545 if (!m_x11window) return;
83df96d6 1546
3cd0b8c5
RR
1547 x = XLOG2DEV(x);
1548 y = YLOG2DEV(y);
83df96d6 1549
2b5f62a0
VZ
1550#if wxUSE_UNICODE
1551 PangoLayout *layout = pango_layout_new(m_context);
1552 pango_layout_set_font_description(layout, m_fontdesc);
ab9d0a8c 1553
2b5f62a0
VZ
1554 const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
1555 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
ab9d0a8c 1556
2b5f62a0
VZ
1557 // Measure layout.
1558 int w,h;
1559 pango_layout_get_pixel_size(layout, &w, &h);
1560 wxCoord width = w;
1561 wxCoord height = h;
ab9d0a8c 1562
2b5f62a0 1563 // Draw layout.
2b77c3fc 1564 x11_draw_layout( (Drawable) m_x11window, (GC) m_textGC, x, y, layout, m_textForegroundColour );
ab9d0a8c 1565
2b5f62a0 1566 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1567
2b5f62a0
VZ
1568 CalcBoundingBox (x + width, y + height);
1569 CalcBoundingBox (x, y);
1570#else
1571 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1572
1573 wxCHECK_RET( xfont, wxT("invalid font") );
ab9d0a8c 1574
ae1daed0
JS
1575 // First draw a rectangle representing the text background, if a text
1576 // background is specified
2b77c3fc 1577 if (m_textBackgroundColour.IsOk () && (m_backgroundMode != wxTRANSPARENT))
83df96d6 1578 {
ae1daed0
JS
1579 // Since X draws from the baseline of the text, must add the text height
1580 int cx = 0;
1581 int cy = 0;
1582 int ascent = 0;
1583 int slen;
1584 int direction, descent;
1585
1586 slen = strlen(text);
1587 XCharStruct overall_return;
1588
3ad2d972 1589 (void)XTextExtents(xfont, (const char*) text.c_str(), slen, &direction,
ae1daed0
JS
1590 &ascent, &descent, &overall_return);
1591
1592 cx = overall_return.width;
1593 cy = ascent + descent;
1594 m_textBackgroundColour.CalcPixel(m_cmap);
6033bbc1 1595 m_textForegroundColour.CalcPixel(m_cmap);
ae1daed0 1596 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
2b77c3fc 1597 XFillRectangle( (Display*) m_display, (Window) m_x11window,
ae1daed0
JS
1598 (GC) m_textGC, x, y, cx, cy );
1599 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
1600
83df96d6 1601 }
3cd0b8c5
RR
1602
1603 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
788519c6 1604#if !wxUSE_NANOX
a4f4d548
JS
1605 // This may be a test for whether the font is 16-bit, but it also
1606 // seems to fail for valid 8-bit fonts too.
1607 if (1) // (xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
788519c6
JS
1608#endif
1609 {
2b77c3fc 1610 XDrawString( (Display*) m_display, (Window) m_x11window,
18680f86 1611 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.length() );
788519c6 1612 }
83df96d6
JS
1613
1614#if 0
3cd0b8c5 1615 if (m_font.GetUnderlined())
83df96d6 1616 {
788519c6 1617 wxCoord ul_y = y + XFontStructGetAscent(font);
3cd0b8c5 1618 if (font->descent > 0) ul_y++;
2b77c3fc 1619 gdk_draw_line( m_x11window, m_textGC, x, ul_y, x + width, ul_y);
83df96d6 1620 }
83df96d6 1621
3cd0b8c5
RR
1622 width = wxCoord(width / m_scaleX);
1623 height = wxCoord(height / m_scaleY);
ab9d0a8c 1624
3cd0b8c5 1625 CalcBoundingBox (x + width, y + height);
83df96d6 1626 CalcBoundingBox (x, y);
3cd0b8c5 1627#endif
2b5f62a0 1628#endif
83df96d6
JS
1629}
1630
2b77c3fc 1631void wxWindowDCImpl::DoDrawRotatedText(const wxString& WXUNUSED(text),
89954433
VZ
1632 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
1633 double WXUNUSED(angle))
83df96d6 1634{
89954433 1635 wxFAIL_MSG( "not implemented" );
83df96d6
JS
1636}
1637
2b77c3fc 1638void wxWindowDCImpl::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
83df96d6 1639 wxCoord *descent, wxCoord *externalLeading,
c94f845b 1640 const wxFont *font ) const
83df96d6 1641{
2b77c3fc 1642 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6 1643
ab9d0a8c 1644 if (string.empty())
2b5f62a0
VZ
1645 {
1646 if (width) (*width) = 0;
1647 if (height) (*height) = 0;
1648 return;
1649 }
ab9d0a8c 1650
2b5f62a0
VZ
1651#if wxUSE_UNICODE
1652 PangoLayout *layout = pango_layout_new( m_context );
1653
1654 if (font)
1655 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
1656 else
1657 pango_layout_set_font_description(layout, m_fontdesc);
ab9d0a8c 1658
2b5f62a0
VZ
1659 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1660 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
ab9d0a8c 1661
2b5f62a0
VZ
1662 // Measure text.
1663 int w,h;
1664 pango_layout_get_pixel_size(layout, &w, &h);
ab9d0a8c
WS
1665
1666 if (width) (*width) = (wxCoord) w;
2b5f62a0
VZ
1667 if (height) (*height) = (wxCoord) h;
1668 if (descent)
1669 {
1670 // Do something about metrics here. TODO.
1671 (*descent) = 0;
1672 }
1673 if (externalLeading) (*externalLeading) = 0; // ??
ab9d0a8c 1674
2b5f62a0
VZ
1675 g_object_unref( G_OBJECT( layout ) );
1676#else
3cd0b8c5
RR
1677 wxFont fontToUse = m_font;
1678 if (font) fontToUse = *font;
83df96d6 1679
2b77c3fc 1680 wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") );
83df96d6 1681
3cd0b8c5 1682 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1683
3cd0b8c5 1684 wxCHECK_RET( xfont, wxT("invalid font") );
ab9d0a8c 1685
83df96d6
JS
1686 int direction, ascent, descent2;
1687 XCharStruct overall;
83df96d6 1688
3ad2d972 1689 XTextExtents( xfont, (const char*) string.c_str(), string.length(), &direction,
83df96d6
JS
1690 &ascent, &descent2, &overall);
1691
3cd0b8c5
RR
1692 if (width)
1693 *width = (wxCoord)( overall.width / m_scaleX );
1694 if (height)
1695 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1696 if (descent)
3cd0b8c5 1697 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1698 if (externalLeading)
3cd0b8c5 1699 *externalLeading = 0; // ??
2b5f62a0 1700#endif
83df96d6
JS
1701}
1702
2b77c3fc 1703wxCoord wxWindowDCImpl::GetCharWidth() const
83df96d6 1704{
2b77c3fc 1705 wxCHECK_MSG( IsOk(), 0, wxT("invalid dc") );
ab9d0a8c 1706
2b5f62a0
VZ
1707#if wxUSE_UNICODE
1708 PangoLayout *layout = pango_layout_new( m_context );
ab9d0a8c 1709
e66faf3d 1710 if (m_fontdesc)
670f9935 1711 pango_layout_set_font_description(layout, m_fontdesc);
e66faf3d 1712 else
670f9935
WS
1713 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1714
2b5f62a0
VZ
1715 pango_layout_set_text(layout, "H", 1 );
1716 int w,h;
1717 pango_layout_get_pixel_size(layout, &w, &h);
1718 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1719
2b5f62a0
VZ
1720 return w;
1721#else
2b77c3fc 1722 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
83df96d6 1723
3cd0b8c5
RR
1724 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1725
1726 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1727
1728 int direction, ascent, descent;
1729 XCharStruct overall;
ab9d0a8c 1730
3cd0b8c5 1731 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1732
3cd0b8c5 1733 return (wxCoord)(overall.width / m_scaleX);
2b5f62a0 1734#endif
83df96d6
JS
1735}
1736
2b77c3fc 1737wxCoord wxWindowDCImpl::GetCharHeight() const
83df96d6 1738{
2b77c3fc 1739 wxCHECK_MSG( IsOk(), 0, wxT("invalid dc") );
ab9d0a8c 1740
2b5f62a0
VZ
1741#if wxUSE_UNICODE
1742 PangoLayout *layout = pango_layout_new( m_context );
ab9d0a8c 1743
e66faf3d 1744 if (m_fontdesc)
670f9935 1745 pango_layout_set_font_description(layout, m_fontdesc);
e66faf3d 1746 else
670f9935
WS
1747 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1748
2b5f62a0
VZ
1749 pango_layout_set_text(layout, "H", 1 );
1750 int w,h;
1751 pango_layout_get_pixel_size(layout, &w, &h);
1752 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1753
2b5f62a0
VZ
1754 return h;
1755#else
2b77c3fc 1756 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
83df96d6 1757
3cd0b8c5
RR
1758 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1759
1760 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1761
1762 int direction, ascent, descent;
1763 XCharStruct overall;
ab9d0a8c 1764
3cd0b8c5 1765 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1766
3cd0b8c5 1767 return (wxCoord)((ascent+descent) / m_scaleY);
2b5f62a0 1768#endif
83df96d6
JS
1769}
1770
2b77c3fc 1771void wxWindowDCImpl::Clear()
83df96d6 1772{
2b77c3fc 1773 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1774
2b77c3fc 1775 if (!m_x11window) return;
83df96d6 1776
3cd0b8c5
RR
1777 /* - we either are a memory dc or have a window as the
1778 owner. anything else shouldn't happen.
1779 - we don't use gdk_window_clear() as we don't set
1780 the window's background colour anymore. it is too
1781 much pain to keep the DC's and the window's back-
1782 ground colour in synch. */
83df96d6 1783
2b77c3fc 1784 if (m_window)
3cd0b8c5
RR
1785 {
1786 int width,height;
2b77c3fc
RR
1787 m_window->GetSize( &width, &height );
1788 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
3cd0b8c5
RR
1789 return;
1790 }
83df96d6 1791
3cd0b8c5
RR
1792 if (m_isMemDC)
1793 {
1794 int width,height;
2b77c3fc
RR
1795 DoGetSize( &width, &height );
1796 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
3cd0b8c5
RR
1797 return;
1798 }
83df96d6
JS
1799}
1800
2b77c3fc 1801void wxWindowDCImpl::SetFont( const wxFont &font )
83df96d6 1802{
2b77c3fc 1803 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6
JS
1804
1805 m_font = font;
670f9935 1806
1175aa4e 1807#if wxUSE_UNICODE
e66faf3d 1808 m_fontdesc = font.GetNativeFontInfo()->description;
1175aa4e 1809#endif
83df96d6
JS
1810}
1811
2b77c3fc 1812void wxWindowDCImpl::SetPen( const wxPen &pen )
83df96d6 1813{
2b77c3fc 1814 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
3cd0b8c5
RR
1815
1816 if (m_pen == pen) return;
83df96d6
JS
1817
1818 m_pen = pen;
83df96d6 1819
2b77c3fc 1820 if (!m_pen.IsOk()) return;
83df96d6 1821
2b77c3fc 1822 if (!m_x11window) return;
83df96d6 1823
3cd0b8c5
RR
1824 int width = m_pen.GetWidth();
1825 if (width <= 0)
1826 {
1827 // CMB: if width is non-zero scale it with the dc
1828 width = 1;
1829 }
1830 else
1831 {
1832 // X doesn't allow different width in x and y and so we take
1833 // the average
1834 double w = 0.5 +
1835 ( fabs((double) XLOG2DEVREL(width)) +
1836 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1837 width = (int)w;
1838 }
1839
1840 static const wxX11Dash dotted[] = {1, 1};
1841 static const wxX11Dash short_dashed[] = {2, 2};
1842 static const wxX11Dash long_dashed[] = {2, 4};
1843 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1844
1845 // We express dash pattern in pen width unit, so we are
1846 // independent of zoom factor and so on...
1847 int req_nb_dash;
1848 const wxX11Dash *req_dash;
1849
1850 int lineStyle = LineSolid;
1851 switch (m_pen.GetStyle())
83df96d6 1852 {
83df96d6 1853 case wxUSER_DASH:
3cd0b8c5
RR
1854 {
1855 lineStyle = LineOnOffDash;
1856 req_nb_dash = m_pen.GetDashCount();
1857 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1858 break;
3cd0b8c5 1859 }
83df96d6 1860 case wxDOT:
3cd0b8c5
RR
1861 {
1862 lineStyle = LineOnOffDash;
83df96d6
JS
1863 req_nb_dash = 2;
1864 req_dash = dotted;
83df96d6 1865 break;
3cd0b8c5 1866 }
83df96d6 1867 case wxLONG_DASH:
3cd0b8c5
RR
1868 {
1869 lineStyle = LineOnOffDash;
83df96d6
JS
1870 req_nb_dash = 2;
1871 req_dash = long_dashed;
83df96d6 1872 break;
3cd0b8c5
RR
1873 }
1874 case wxSHORT_DASH:
1875 {
1876 lineStyle = LineOnOffDash;
1877 req_nb_dash = 2;
1878 req_dash = short_dashed;
1879 break;
1880 }
83df96d6 1881 case wxDOT_DASH:
3cd0b8c5
RR
1882 {
1883// lineStyle = LineDoubleDash;
1884 lineStyle = LineOnOffDash;
83df96d6
JS
1885 req_nb_dash = 4;
1886 req_dash = dotted_dashed;
83df96d6 1887 break;
3cd0b8c5
RR
1888 }
1889
1890 case wxTRANSPARENT:
1891 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1892 case wxSTIPPLE:
1893 case wxSOLID:
83df96d6 1894 default:
3cd0b8c5
RR
1895 {
1896 lineStyle = LineSolid;
74dc5eb6 1897 req_dash = (wxX11Dash*)NULL;
83df96d6 1898 req_nb_dash = 0;
3cd0b8c5 1899 break;
83df96d6 1900 }
3cd0b8c5 1901 }
83df96d6 1902
3cd0b8c5
RR
1903 int capStyle = CapRound;
1904 switch (m_pen.GetCap())
1905 {
1906 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1907 case wxCAP_BUTT: { capStyle = CapButt; break; }
1908 case wxCAP_ROUND:
1909 default:
83df96d6 1910 {
3cd0b8c5 1911 if (width <= 1)
83df96d6 1912 {
3cd0b8c5
RR
1913 width = 0;
1914 capStyle = CapNotLast;
83df96d6
JS
1915 }
1916 else
1917 {
3cd0b8c5 1918 capStyle = CapRound;
83df96d6 1919 }
83df96d6
JS
1920 break;
1921 }
3cd0b8c5 1922 }
83df96d6 1923
3cd0b8c5
RR
1924 int joinStyle = JoinRound;
1925 switch (m_pen.GetJoin())
1926 {
1927 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1928 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1929 case wxJOIN_ROUND:
3cd0b8c5 1930 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1931 }
1932
3cd0b8c5 1933 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1934
3cd0b8c5
RR
1935 m_pen.GetColour().CalcPixel( m_cmap );
1936 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1937}
83df96d6 1938
2b77c3fc 1939void wxWindowDCImpl::SetBrush( const wxBrush &brush )
3cd0b8c5 1940{
2b77c3fc 1941 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1942
3cd0b8c5 1943 if (m_brush == brush) return;
83df96d6 1944
3cd0b8c5
RR
1945 m_brush = brush;
1946
2b77c3fc 1947 if (!m_brush.IsOk()) return;
83df96d6 1948
2b77c3fc 1949 if (!m_x11window) return;
3cd0b8c5
RR
1950
1951 m_brush.GetColour().CalcPixel( m_cmap );
1952 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
ab9d0a8c 1953
3cd0b8c5
RR
1954 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1955
2b77c3fc 1956 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->IsOk()))
83df96d6 1957 {
3cd0b8c5 1958 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1959 {
3cd0b8c5
RR
1960 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1961 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1962 }
1963 else
1964 {
3cd0b8c5 1965 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1966 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1967 }
3cd0b8c5 1968 }
83df96d6 1969
3cd0b8c5
RR
1970 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1971 {
1972 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1973 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1974 }
83df96d6 1975
ab9d0a8c 1976 if (m_brush.IsHatch())
3cd0b8c5
RR
1977 {
1978 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1979 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1980 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1981 }
83df96d6
JS
1982}
1983
2b77c3fc 1984void wxWindowDCImpl::SetBackground( const wxBrush &brush )
83df96d6 1985{
3cd0b8c5
RR
1986 /* CMB 21/7/98: Added SetBackground. Sets background brush
1987 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 1988
2b77c3fc 1989 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1990
3cd0b8c5 1991 if (m_backgroundBrush == brush) return;
83df96d6 1992
3cd0b8c5 1993 m_backgroundBrush = brush;
83df96d6 1994
2b77c3fc 1995 if (!m_backgroundBrush.IsOk()) return;
83df96d6 1996
2b77c3fc 1997 if (!m_x11window) return;
83df96d6 1998
3cd0b8c5
RR
1999 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
2000 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
2001 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
2002 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
2003 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 2004
3cd0b8c5 2005 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 2006
2b77c3fc 2007 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->IsOk()))
83df96d6 2008 {
3cd0b8c5 2009 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 2010 {
3cd0b8c5
RR
2011 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
2012 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 2013 }
3cd0b8c5 2014 else
83df96d6 2015 {
3cd0b8c5 2016 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 2017 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 2018 }
83df96d6
JS
2019 }
2020
ab9d0a8c 2021 if (m_backgroundBrush.IsHatch())
83df96d6 2022 {
3cd0b8c5
RR
2023 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
2024 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
2025 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 2026 }
83df96d6
JS
2027}
2028
2b77c3fc 2029void wxWindowDCImpl::SetLogicalFunction( int function )
83df96d6 2030{
2b77c3fc 2031 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6
JS
2032
2033 int x_function;
2034
83df96d6
JS
2035 if (m_logicalFunction == function)
2036 return;
2037
3cd0b8c5 2038 // VZ: shouldn't this be a CHECK?
2b77c3fc 2039 if (!m_x11window)
3cd0b8c5 2040 return;
ab9d0a8c 2041
83df96d6
JS
2042 switch (function)
2043 {
2044 case wxCLEAR:
2045 x_function = GXclear;
2046 break;
2047 case wxXOR:
2048 x_function = GXxor;
2049 break;
2050 case wxINVERT:
2051 x_function = GXinvert;
2052 break;
2053 case wxOR_REVERSE:
2054 x_function = GXorReverse;
2055 break;
2056 case wxAND_REVERSE:
2057 x_function = GXandReverse;
2058 break;
2059 case wxAND:
2060 x_function = GXand;
2061 break;
2062 case wxOR:
2063 x_function = GXor;
2064 break;
2065 case wxAND_INVERT:
2066 x_function = GXandInverted;
2067 break;
2068 case wxNO_OP:
2069 x_function = GXnoop;
2070 break;
2071 case wxNOR:
2072 x_function = GXnor;
2073 break;
2074 case wxEQUIV:
2075 x_function = GXequiv;
2076 break;
2077 case wxSRC_INVERT:
2078 x_function = GXcopyInverted;
2079 break;
2080 case wxOR_INVERT:
2081 x_function = GXorInverted;
2082 break;
2083 case wxNAND:
2084 x_function = GXnand;
2085 break;
2086 case wxSET:
2087 x_function = GXset;
2088 break;
2089 case wxCOPY:
2090 default:
2091 x_function = GXcopy;
2092 break;
2093 }
2094
3cd0b8c5
RR
2095 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2096 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 2097
3cd0b8c5
RR
2098 // to stay compatible with wxMSW, we don't apply ROPs to the text
2099 // operations (i.e. DrawText/DrawRotatedText).
2100 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2101 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
ab9d0a8c 2102
83df96d6 2103 m_logicalFunction = function;
83df96d6
JS
2104}
2105
2b77c3fc 2106void wxWindowDCImpl::SetTextForeground( const wxColour &col )
83df96d6 2107{
2b77c3fc 2108 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2109
3cd0b8c5
RR
2110 // don't set m_textForegroundColour to an invalid colour as we'd crash
2111 // later then (we use m_textForegroundColour.GetColor() without checking
2112 // in a few places)
2b77c3fc 2113 if ( !col.IsOk() || (m_textForegroundColour == col) )
83df96d6
JS
2114 return;
2115
2116 m_textForegroundColour = col;
2117
2b77c3fc 2118 if (m_x11window)
3cd0b8c5
RR
2119 {
2120 m_textForegroundColour.CalcPixel( m_cmap );
2121 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2122 }
83df96d6
JS
2123}
2124
2b77c3fc 2125void wxWindowDCImpl::SetTextBackground( const wxColour &col )
83df96d6 2126{
2b77c3fc 2127 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2128
3cd0b8c5 2129 // same as above
2b77c3fc 2130 if ( !col.IsOk() || (m_textBackgroundColour == col) )
83df96d6
JS
2131 return;
2132
2133 m_textBackgroundColour = col;
3cd0b8c5 2134
2b77c3fc 2135 if (m_x11window)
3cd0b8c5
RR
2136 {
2137 m_textBackgroundColour.CalcPixel( m_cmap );
2138 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2139 }
83df96d6
JS
2140}
2141
2b77c3fc 2142void wxWindowDCImpl::SetBackgroundMode( int mode )
83df96d6 2143{
2b77c3fc 2144 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
3cd0b8c5 2145
83df96d6 2146 m_backgroundMode = mode;
3cd0b8c5 2147
0b5c0e1a
JS
2148#if wxUSE_NANOX
2149 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2150#endif
2151
2b77c3fc 2152 if (!m_x11window) return;
3cd0b8c5
RR
2153
2154 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2155 // transparent/solid background mode
2156
2157 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2158 {
2159 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2160 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2161 }
83df96d6
JS
2162}
2163
2b77c3fc 2164void wxWindowDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) )
83df96d6 2165{
3cd0b8c5 2166#if 0
2b77c3fc 2167 if (m_x11window)
83df96d6 2168 {
2b77c3fc 2169 if (palette.IsOk())
83df96d6 2170 /* Use GetXColormap */
2b77c3fc 2171 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
83df96d6
JS
2172 (Colormap) palette.GetXColormap());
2173 else
2174 /* Use wxGetMainColormap */
2b77c3fc 2175 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
83df96d6
JS
2176 (Colormap) wxTheApp->GetMainColormap(m_display));
2177 }
3cd0b8c5 2178#endif
83df96d6
JS
2179}
2180
2b77c3fc 2181void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 2182{
2b77c3fc 2183 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2184
2b77c3fc 2185 if (!m_x11window) return;
83df96d6 2186
41e52241
JS
2187 if (width <= 0)
2188 width = 1;
2189
2190 if (height <= 0)
2191 height = 1;
2192
3cd0b8c5
RR
2193 wxRect rect;
2194 rect.x = XLOG2DEV(x);
2195 rect.y = YLOG2DEV(y);
2196 rect.width = XLOG2DEVREL(width);
2197 rect.height = YLOG2DEVREL(height);
2198
6dd25d20 2199 if (!m_currentClippingRegion.IsEmpty())
3cd0b8c5 2200 m_currentClippingRegion.Intersect( rect );
83df96d6 2201 else
6dd25d20 2202 m_currentClippingRegion = rect;
3cd0b8c5
RR
2203
2204#if USE_PAINT_REGION
6dd25d20 2205 if (!m_paintClippingRegion.IsEmpty())
3cd0b8c5
RR
2206 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2207#endif
2208
2209 wxCoord xx, yy, ww, hh;
2210 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2b77c3fc 2211 wxDCImpl::DoSetClippingRegion( xx, yy, ww, hh );
3cd0b8c5
RR
2212
2213 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2214 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2215 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2216 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2217}
83df96d6 2218
2b77c3fc 2219void wxWindowDCImpl::DoSetClippingRegionAsRegion( const wxRegion& region )
3cd0b8c5 2220{
2b77c3fc 2221 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2222
3cd0b8c5 2223 if (region.Empty())
83df96d6 2224 {
3cd0b8c5
RR
2225 DestroyClippingRegion();
2226 return;
83df96d6 2227 }
3cd0b8c5 2228
2b77c3fc 2229 if (!m_x11window) return;
3cd0b8c5 2230
6dd25d20 2231 if (!m_currentClippingRegion.IsEmpty())
3cd0b8c5 2232 m_currentClippingRegion.Intersect( region );
83df96d6 2233 else
6dd25d20 2234 m_currentClippingRegion = region;
83df96d6 2235
3cd0b8c5 2236#if USE_PAINT_REGION
6dd25d20 2237 if (!m_paintClippingRegion.IsEmpty())
3cd0b8c5
RR
2238 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2239#endif
83df96d6 2240
3cd0b8c5
RR
2241 wxCoord xx, yy, ww, hh;
2242 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2b77c3fc 2243 wxDCImpl::DoSetClippingRegion( xx, yy, ww, hh );
3cd0b8c5
RR
2244
2245 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2246 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2247 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2248 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
2249}
2250
2b77c3fc 2251void wxWindowDCImpl::DestroyClippingRegion()
83df96d6 2252{
2b77c3fc 2253 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2254
2b77c3fc 2255 wxDCImpl::DestroyClippingRegion();
83df96d6 2256
3cd0b8c5 2257 m_currentClippingRegion.Clear();
83df96d6 2258
3cd0b8c5
RR
2259#if USE_PAINT_REGION
2260 if (!m_paintClippingRegion.IsEmpty())
2261 m_currentClippingRegion.Union( m_paintClippingRegion );
2262#endif
83df96d6 2263
2b77c3fc 2264 if (!m_x11window) return;
83df96d6 2265
3cd0b8c5
RR
2266 if (m_currentClippingRegion.IsEmpty())
2267 {
2268 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2269 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2270 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2271 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2272 }
2273 else
2274 {
2275 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2276 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2277 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2278 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2279 }
2280}
83df96d6 2281
2b77c3fc 2282void wxWindowDCImpl::Destroy()
83df96d6 2283{
3cd0b8c5
RR
2284 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2285 m_penGC = NULL;
2286 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2287 m_brushGC = NULL;
2288 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2289 m_textGC = NULL;
2290 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2291 m_bgGC = NULL;
2292}
83df96d6 2293
2b77c3fc 2294void wxWindowDCImpl::ComputeScaleAndOrigin()
3cd0b8c5
RR
2295{
2296 /* CMB: copy scale to see if it changes */
2297 double origScaleX = m_scaleX;
2298 double origScaleY = m_scaleY;
83df96d6 2299
2b77c3fc 2300 wxDCImpl::ComputeScaleAndOrigin();
83df96d6 2301
3cd0b8c5
RR
2302 /* CMB: if scale has changed call SetPen to recalulate the line width */
2303 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2b77c3fc 2304 (m_pen.IsOk()))
3cd0b8c5
RR
2305 {
2306 /* this is a bit artificial, but we need to force wxDC to think
2307 the pen has changed */
2308 wxPen pen = m_pen;
2309 m_pen = wxNullPen;
2310 SetPen( pen );
2311 }
83df96d6
JS
2312}
2313
2b77c3fc 2314wxSize wxWindowDCImpl::GetPPI() const
83df96d6
JS
2315{
2316 return wxSize(100, 100);
2317}
2318
2b77c3fc 2319int wxWindowDCImpl::GetDepth() const
83df96d6 2320{
3cd0b8c5 2321 wxFAIL_MSG(wxT("not implemented"));
83df96d6 2322
3cd0b8c5
RR
2323 return -1;
2324}
83df96d6 2325
3cd0b8c5
RR
2326//-----------------------------------------------------------------------------
2327// wxClientDC
2328//-----------------------------------------------------------------------------
2329
03580f20 2330IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
3cd0b8c5 2331
2b77c3fc
RR
2332wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window )
2333 : wxWindowDCImpl( owner, window )
83df96d6 2334{
ab6b6b15 2335 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
ab9d0a8c 2336
2b77c3fc 2337 m_x11window = (WXWindow*) window->GetClientAreaWindow();
ab9d0a8c 2338
2b5f62a0 2339 // Adjust the client area when the wxWindow is not using 2 X11 windows.
2b77c3fc 2340 if (m_x11window == (WXWindow*) window->GetMainWindow())
7948c0c2 2341 {
c2c0dabf
RR
2342 wxPoint ptOrigin = window->GetClientAreaOrigin();
2343 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2344 wxSize size = window->GetClientSize();
2b77c3fc 2345 DoSetClippingRegion( 0, 0, size.x, size.y );
7948c0c2 2346 }
83df96d6
JS
2347}
2348
2b77c3fc 2349void wxClientDCImpl::DoGetSize(int *width, int *height) const
83df96d6 2350{
2b77c3fc 2351 wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") );
3cd0b8c5 2352
2b77c3fc 2353 m_window->GetClientSize( width, height );
83df96d6
JS
2354}
2355
ab6b6b15
RR
2356// ----------------------------------------------------------------------------
2357// wxPaintDC
2358// ----------------------------------------------------------------------------
2359
2b77c3fc 2360IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxClientDCImpl)
ab6b6b15 2361
2b77c3fc
RR
2362wxPaintDCImpl::wxPaintDCImpl(wxDC *owner, wxWindow* window)
2363 : wxClientDCImpl(owner, window)
ab6b6b15
RR
2364{
2365#if USE_PAINT_REGION
2366 if (!window->GetClipPaintRegion())
2367 return;
2368
2369 m_paintClippingRegion = window->GetUpdateRegion();
2370 Region region = (Region) m_paintClippingRegion.GetX11Region();
2371 if (region)
2372 {
2373 m_currentClippingRegion.Union( m_paintClippingRegion );
2374
2375 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2376 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2377 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2378 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2379 }
2380#endif // USE_PAINT_REGION
2381}
2382
83df96d6 2383// ----------------------------------------------------------------------------
3cd0b8c5 2384// wxDCModule
83df96d6
JS
2385// ----------------------------------------------------------------------------
2386
3cd0b8c5 2387class wxDCModule : public wxModule
83df96d6 2388{
3cd0b8c5 2389public:
b886fae6
VZ
2390 // we must be cleaned up before wxDisplayModule which closes the global
2391 // display
2392 wxDCModule()
2393 {
2394 AddDependency(wxClassInfo::FindClass(_T("wxX11DisplayModule")));
2395 }
2396
2397 bool OnInit() { wxInitGCPool(); return true; }
2398 void OnExit() { wxCleanUpGCPool(); }
83df96d6 2399
3cd0b8c5
RR
2400private:
2401 DECLARE_DYNAMIC_CLASS(wxDCModule)
2402};
83df96d6 2403
3cd0b8c5 2404IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 2405