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