]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
Converted wxVariant to use wxObject's reference counting facilities. Should make...
[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 64static Pixmap hatches[num_hatches];
d3b9f782 65static Pixmap *hatch_bitmap = NULL;
3cd0b8c5
RR
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{
d3b9f782
VZ
225 m_display = NULL;
226 m_penGC = NULL;
227 m_brushGC = NULL;
228 m_textGC = NULL;
229 m_bgGC = NULL;
230 m_cmap = NULL;
2b77c3fc
RR
231 m_isMemDC = false;
232 m_isScreenDC = false;
d3b9f782 233 m_x11window = NULL;
2b77c3fc
RR
234
235#if wxUSE_UNICODE
236 m_context = wxTheApp->GetPangoContext();
d3b9f782 237 m_fontdesc = NULL;
2b77c3fc
RR
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,
89efaf2b 354 const wxColour & col, wxFloodFillStyle style);
b1699cd3 355
2b77c3fc 356bool wxWindowDCImpl::DoFloodFill(wxCoord x, wxCoord y,
89efaf2b 357 const wxColour& col, wxFloodFillStyle style)
3a0a5ada 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 645 wxCoord xoffset, wxCoord yoffset,
89efaf2b 646 wxPolygonFillMode 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,
89efaf2b
FM
1294 wxDC *source, wxCoord xsrc, wxCoord ysrc,
1295 wxRasterOperationMode logical_func, bool useMask,
83df96d6
JS
1296 wxCoord xsrcMask, wxCoord ysrcMask )
1297{
3cd0b8c5
RR
1298 /* this is the nth try to get this utterly useless function to
1299 work. it now completely ignores the scaling or translation
1300 of the source dc, but scales correctly on the target dc and
1301 knows about possible mask information in a memory dc. */
83df96d6 1302
2b77c3fc 1303 wxCHECK_MSG( IsOk(), false, wxT("invalid window dc") );
83df96d6 1304
ab9d0a8c 1305 wxCHECK_MSG( source, false, wxT("invalid source dc") );
83df96d6 1306
2b77c3fc 1307 if (!m_x11window) return false;
83df96d6 1308
3cd0b8c5 1309 // transform the source DC coords to the device ones
d3ae69de
VZ
1310 xsrc = source->LogicalToDeviceX(xsrc);
1311 ysrc = source->LogicalToDeviceY(ysrc);
83df96d6 1312
3cd0b8c5
RR
1313 wxClientDC *srcDC = (wxClientDC*)source;
1314 wxMemoryDC *memDC = (wxMemoryDC*)source;
2b77c3fc 1315 wxWindowDCImpl *src_impl = (wxWindowDCImpl*) srcDC->GetImpl();
83df96d6 1316
ab9d0a8c
WS
1317 bool use_bitmap_method = false;
1318 bool is_mono = false;
83df96d6 1319
ab9d0a8c 1320 // TODO: use the mask origin when drawing transparently
83df96d6
JS
1321 if (xsrcMask == -1 && ysrcMask == -1)
1322 {
b1633d20
RR
1323 xsrcMask = xsrc;
1324 ysrcMask = ysrc;
83df96d6 1325 }
ab9d0a8c 1326
2b77c3fc 1327 if (src_impl->m_isMemDC)
83df96d6 1328 {
2b77c3fc 1329 wxBitmap selected = memDC->GetSelectedBitmap();
8ca1b2c5 1330
2b77c3fc 1331 if (!selected.IsOk()) return false;
83df96d6 1332
3cd0b8c5
RR
1333 /* we use the "XCopyArea" way to copy a memory dc into
1334 y different window if the memory dc BOTH
1335 a) doesn't have any mask or its mask isn't used
1336 b) it is clipped
1337 c) is not 1-bit */
83df96d6 1338
2b77c3fc 1339 if (useMask && (selected.GetMask()))
83df96d6 1340 {
3cd0b8c5
RR
1341 /* we HAVE TO use the direct way for memory dcs
1342 that have mask since the XCopyArea doesn't know
1343 about masks */
ab9d0a8c 1344 use_bitmap_method = true;
3cd0b8c5 1345 }
2b77c3fc 1346 else if (selected.GetDepth() == 1)
3cd0b8c5
RR
1347 {
1348 /* we HAVE TO use the direct way for memory dcs
1349 that are bitmaps because XCopyArea doesn't cope
1350 with different bit depths */
ab9d0a8c
WS
1351 is_mono = true;
1352 use_bitmap_method = true;
3cd0b8c5
RR
1353 }
1354 else if ((xsrc == 0) && (ysrc == 0) &&
2b77c3fc
RR
1355 (width == selected.GetWidth()) &&
1356 (height == selected.GetHeight()))
3cd0b8c5
RR
1357 {
1358 /* we SHOULD use the direct way if all of the bitmap
1359 in the memory dc is copied in which case XCopyArea
1360 wouldn't be able able to boost performace by reducing
1361 the area to be scaled */
ab9d0a8c 1362 use_bitmap_method = true;
83df96d6
JS
1363 }
1364 else
1365 {
ab9d0a8c 1366 use_bitmap_method = false;
83df96d6
JS
1367 }
1368 }
83df96d6 1369
3cd0b8c5
RR
1370 CalcBoundingBox( xdest, ydest );
1371 CalcBoundingBox( xdest + width, ydest + height );
1372
b1633d20 1373 // scale/translate size and position
3cd0b8c5
RR
1374 wxCoord xx = XLOG2DEV(xdest);
1375 wxCoord yy = YLOG2DEV(ydest);
1376
1377 wxCoord ww = XLOG2DEVREL(width);
1378 wxCoord hh = YLOG2DEVREL(height);
1379
b1633d20 1380 // compare to current clipping region
3cd0b8c5 1381 if (!m_currentClippingRegion.IsNull())
83df96d6 1382 {
3cd0b8c5
RR
1383 wxRegion tmp( xx,yy,ww,hh );
1384 tmp.Intersect( m_currentClippingRegion );
1385 if (tmp.IsEmpty())
ab9d0a8c 1386 return true;
3cd0b8c5 1387 }
83df96d6 1388
89efaf2b 1389 wxRasterOperationMode old_logical_func = m_logicalFunction;
3cd0b8c5 1390 SetLogicalFunction( logical_func );
83df96d6 1391
3cd0b8c5
RR
1392 if (use_bitmap_method)
1393 {
2b77c3fc 1394 wxBitmap selected = memDC->GetSelectedBitmap();
8ca1b2c5 1395
b1633d20 1396 // scale/translate bitmap size
2b77c3fc
RR
1397 wxCoord bm_width = selected.GetWidth();
1398 wxCoord bm_height = selected.GetHeight();
83df96d6 1399
3cd0b8c5
RR
1400 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1401 wxCoord bm_hh = YLOG2DEVREL( bm_height );
83df96d6 1402
b1633d20 1403 // scale bitmap if required
3cd0b8c5 1404 wxBitmap use_bitmap;
83df96d6 1405
3cd0b8c5
RR
1406 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1407 {
2b77c3fc 1408 wxImage image( selected.ConvertToImage() );
3cd0b8c5 1409 image = image.Scale( bm_ww, bm_hh );
83df96d6 1410
b1633d20 1411#if 0
3cd0b8c5
RR
1412 if (is_mono)
1413 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1414 else
b1633d20 1415#endif
2b5f62a0 1416 use_bitmap = image;
3cd0b8c5
RR
1417 }
1418 else
1419 {
2b77c3fc 1420 use_bitmap = selected;
3cd0b8c5
RR
1421 }
1422
b1633d20
RR
1423 // apply mask if any
1424 WXPixmap mask = NULL;
3cd0b8c5 1425 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
83df96d6 1426
3cd0b8c5 1427 if (useMask && mask)
83df96d6 1428 {
b1633d20
RR
1429 WXPixmap new_mask = NULL;
1430#if 0
3cd0b8c5 1431 if (!m_currentClippingRegion.IsNull())
83df96d6 1432 {
3cd0b8c5
RR
1433 GdkColor col;
1434 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1435 GdkGC *gc = gdk_gc_new( new_mask );
1436 col.pixel = 0;
1437 gdk_gc_set_foreground( gc, &col );
1438 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1439 col.pixel = 0;
1440 gdk_gc_set_background( gc, &col );
1441 col.pixel = 1;
1442 gdk_gc_set_foreground( gc, &col );
1443 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1444 gdk_gc_set_clip_origin( gc, -xx, -yy );
1445 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1446 gdk_gc_set_stipple( gc, mask );
1447 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1448 gdk_gc_unref( gc );
83df96d6 1449 }
b1633d20 1450#endif
3cd0b8c5 1451 if (is_mono)
83df96d6 1452 {
3cd0b8c5 1453 if (new_mask)
b1633d20 1454 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 1455 else
b1633d20
RR
1456 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1457 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
83df96d6
JS
1458 }
1459 else
1460 {
3cd0b8c5 1461 if (new_mask)
b1633d20 1462 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 1463 else
b1633d20
RR
1464 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1465 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
83df96d6 1466 }
ab9d0a8c 1467
3cd0b8c5 1468 if (new_mask)
b1633d20 1469 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 1470 }
83df96d6 1471
b1633d20
RR
1472 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1473 // drawing a mono-bitmap (XBitmap) we use the current text GC
3cd0b8c5 1474 if (is_mono)
2b77c3fc 1475 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_x11window,
b1633d20 1476 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
83df96d6 1477 else
2b77c3fc 1478 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_x11window,
b1633d20 1479 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
83df96d6 1480
b1633d20 1481 // remove mask again if any
3cd0b8c5 1482 if (useMask && mask)
83df96d6 1483 {
3cd0b8c5
RR
1484 if (is_mono)
1485 {
b1633d20
RR
1486 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1487 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 1488 if (!m_currentClippingRegion.IsNull())
b1633d20 1489 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
3cd0b8c5
RR
1490 }
1491 else
83df96d6 1492 {
b1633d20
RR
1493 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1494 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 1495 if (!m_currentClippingRegion.IsNull())
b1633d20 1496 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1497 }
1498 }
83df96d6 1499 }
b1633d20 1500 else // use_bitmap_method
83df96d6 1501 {
ab70c3bb
RR
1502 wxDCImpl *impl = srcDC->GetImpl();
1503 wxWindowDCImpl *x11_impl = wxDynamicCast(impl, wxWindowDCImpl);
1504 if (!x11_impl)
1505 {
1506 SetLogicalFunction( old_logical_func );
1507 return false;
1508 }
8ca1b2c5 1509
3cd0b8c5 1510 if ((width != ww) || (height != hh))
83df96d6 1511 {
b1633d20 1512 /* Draw source window into a bitmap as we cannot scale
3cd0b8c5
RR
1513 a window in contrast to a bitmap. this would actually
1514 work with memory dcs as well, but we'd lose the mask
1515 information and waste one step in this process since
1516 a memory already has a bitmap. all this is slightly
1517 inefficient as we could take an XImage directly from
1518 an X window, but we'd then also have to care that
1519 the window is not outside the screen (in which case
1520 we'd get a BadMatch or what not).
1521 Is a double XGetImage and combined XGetPixel and
1522 XPutPixel really faster? I'm not sure. look at wxXt
1523 for a different implementation of the same problem. */
1524
1525 wxBitmap bitmap( width, height );
1526
b1633d20
RR
1527 // copy including child window contents
1528 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
73f46291 1529 XCopyArea( (Display*) m_display, (Window) x11_impl->GetX11Window(), (Window) bitmap.GetPixmap(),
b1633d20
RR
1530 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1531 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1532
b1633d20 1533 // scale image
2b5f62a0 1534 wxImage image( bitmap.ConvertToImage() );
3cd0b8c5
RR
1535 image = image.Scale( ww, hh );
1536
b1633d20 1537 // convert to bitmap
2b5f62a0 1538 bitmap = image;
3cd0b8c5 1539
b1633d20 1540 // draw scaled bitmap
2b77c3fc 1541 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_x11window,
b1633d20 1542 (GC) m_penGC, 0, 0, width, height, xx, yy );
83df96d6
JS
1543 }
1544 else
3cd0b8c5 1545 {
b1633d20 1546 // No scaling and not a memory dc with a mask either
b1633d20
RR
1547 // copy including child window contents
1548 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
73f46291 1549 XCopyArea( (Display*) m_display, (Window) x11_impl->GetX11Window(), (Window) m_x11window,
b1633d20
RR
1550 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1551 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1552 }
83df96d6
JS
1553 }
1554
3cd0b8c5 1555 SetLogicalFunction( old_logical_func );
ab9d0a8c
WS
1556
1557 return true;
83df96d6
JS
1558}
1559
2b77c3fc 1560void wxWindowDCImpl::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
83df96d6 1561{
2b77c3fc 1562 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1563
2b77c3fc 1564 if (!m_x11window) return;
83df96d6 1565
3cd0b8c5
RR
1566 x = XLOG2DEV(x);
1567 y = YLOG2DEV(y);
83df96d6 1568
2b5f62a0
VZ
1569#if wxUSE_UNICODE
1570 PangoLayout *layout = pango_layout_new(m_context);
1571 pango_layout_set_font_description(layout, m_fontdesc);
ab9d0a8c 1572
2b5f62a0
VZ
1573 const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
1574 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
ab9d0a8c 1575
2b5f62a0
VZ
1576 // Measure layout.
1577 int w,h;
1578 pango_layout_get_pixel_size(layout, &w, &h);
1579 wxCoord width = w;
1580 wxCoord height = h;
ab9d0a8c 1581
2b5f62a0 1582 // Draw layout.
2b77c3fc 1583 x11_draw_layout( (Drawable) m_x11window, (GC) m_textGC, x, y, layout, m_textForegroundColour );
ab9d0a8c 1584
2b5f62a0 1585 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1586
2b5f62a0
VZ
1587 CalcBoundingBox (x + width, y + height);
1588 CalcBoundingBox (x, y);
1589#else
1590 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1591
1592 wxCHECK_RET( xfont, wxT("invalid font") );
ab9d0a8c 1593
ae1daed0
JS
1594 // First draw a rectangle representing the text background, if a text
1595 // background is specified
2b77c3fc 1596 if (m_textBackgroundColour.IsOk () && (m_backgroundMode != wxTRANSPARENT))
83df96d6 1597 {
ae1daed0
JS
1598 // Since X draws from the baseline of the text, must add the text height
1599 int cx = 0;
1600 int cy = 0;
1601 int ascent = 0;
1602 int slen;
1603 int direction, descent;
1604
1605 slen = strlen(text);
1606 XCharStruct overall_return;
1607
3ad2d972 1608 (void)XTextExtents(xfont, (const char*) text.c_str(), slen, &direction,
ae1daed0
JS
1609 &ascent, &descent, &overall_return);
1610
1611 cx = overall_return.width;
1612 cy = ascent + descent;
1613 m_textBackgroundColour.CalcPixel(m_cmap);
6033bbc1 1614 m_textForegroundColour.CalcPixel(m_cmap);
ae1daed0 1615 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
2b77c3fc 1616 XFillRectangle( (Display*) m_display, (Window) m_x11window,
ae1daed0
JS
1617 (GC) m_textGC, x, y, cx, cy );
1618 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
1619
83df96d6 1620 }
3cd0b8c5
RR
1621
1622 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
788519c6 1623#if !wxUSE_NANOX
a4f4d548
JS
1624 // This may be a test for whether the font is 16-bit, but it also
1625 // seems to fail for valid 8-bit fonts too.
1626 if (1) // (xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
788519c6
JS
1627#endif
1628 {
2b77c3fc 1629 XDrawString( (Display*) m_display, (Window) m_x11window,
18680f86 1630 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.length() );
788519c6 1631 }
83df96d6
JS
1632
1633#if 0
3cd0b8c5 1634 if (m_font.GetUnderlined())
83df96d6 1635 {
788519c6 1636 wxCoord ul_y = y + XFontStructGetAscent(font);
3cd0b8c5 1637 if (font->descent > 0) ul_y++;
2b77c3fc 1638 gdk_draw_line( m_x11window, m_textGC, x, ul_y, x + width, ul_y);
83df96d6 1639 }
83df96d6 1640
3cd0b8c5
RR
1641 width = wxCoord(width / m_scaleX);
1642 height = wxCoord(height / m_scaleY);
ab9d0a8c 1643
3cd0b8c5 1644 CalcBoundingBox (x + width, y + height);
83df96d6 1645 CalcBoundingBox (x, y);
3cd0b8c5 1646#endif
2b5f62a0 1647#endif
83df96d6
JS
1648}
1649
2b77c3fc 1650void wxWindowDCImpl::DoDrawRotatedText(const wxString& WXUNUSED(text),
89954433
VZ
1651 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
1652 double WXUNUSED(angle))
83df96d6 1653{
89954433 1654 wxFAIL_MSG( "not implemented" );
83df96d6
JS
1655}
1656
2b77c3fc 1657void wxWindowDCImpl::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
83df96d6 1658 wxCoord *descent, wxCoord *externalLeading,
c94f845b 1659 const wxFont *font ) const
83df96d6 1660{
2b77c3fc 1661 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6 1662
ab9d0a8c 1663 if (string.empty())
2b5f62a0
VZ
1664 {
1665 if (width) (*width) = 0;
1666 if (height) (*height) = 0;
1667 return;
1668 }
ab9d0a8c 1669
2b5f62a0
VZ
1670#if wxUSE_UNICODE
1671 PangoLayout *layout = pango_layout_new( m_context );
1672
1673 if (font)
1674 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
1675 else
1676 pango_layout_set_font_description(layout, m_fontdesc);
ab9d0a8c 1677
2b5f62a0
VZ
1678 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1679 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
ab9d0a8c 1680
2b5f62a0
VZ
1681 // Measure text.
1682 int w,h;
1683 pango_layout_get_pixel_size(layout, &w, &h);
ab9d0a8c
WS
1684
1685 if (width) (*width) = (wxCoord) w;
2b5f62a0
VZ
1686 if (height) (*height) = (wxCoord) h;
1687 if (descent)
1688 {
1689 // Do something about metrics here. TODO.
1690 (*descent) = 0;
1691 }
1692 if (externalLeading) (*externalLeading) = 0; // ??
ab9d0a8c 1693
2b5f62a0
VZ
1694 g_object_unref( G_OBJECT( layout ) );
1695#else
3cd0b8c5
RR
1696 wxFont fontToUse = m_font;
1697 if (font) fontToUse = *font;
83df96d6 1698
2b77c3fc 1699 wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") );
83df96d6 1700
3cd0b8c5 1701 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1702
3cd0b8c5 1703 wxCHECK_RET( xfont, wxT("invalid font") );
ab9d0a8c 1704
83df96d6
JS
1705 int direction, ascent, descent2;
1706 XCharStruct overall;
83df96d6 1707
3ad2d972 1708 XTextExtents( xfont, (const char*) string.c_str(), string.length(), &direction,
83df96d6
JS
1709 &ascent, &descent2, &overall);
1710
3cd0b8c5
RR
1711 if (width)
1712 *width = (wxCoord)( overall.width / m_scaleX );
1713 if (height)
1714 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1715 if (descent)
3cd0b8c5 1716 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1717 if (externalLeading)
3cd0b8c5 1718 *externalLeading = 0; // ??
2b5f62a0 1719#endif
83df96d6
JS
1720}
1721
2b77c3fc 1722wxCoord wxWindowDCImpl::GetCharWidth() const
83df96d6 1723{
2b77c3fc 1724 wxCHECK_MSG( IsOk(), 0, wxT("invalid dc") );
ab9d0a8c 1725
2b5f62a0
VZ
1726#if wxUSE_UNICODE
1727 PangoLayout *layout = pango_layout_new( m_context );
ab9d0a8c 1728
e66faf3d 1729 if (m_fontdesc)
670f9935 1730 pango_layout_set_font_description(layout, m_fontdesc);
e66faf3d 1731 else
670f9935
WS
1732 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1733
2b5f62a0
VZ
1734 pango_layout_set_text(layout, "H", 1 );
1735 int w,h;
1736 pango_layout_get_pixel_size(layout, &w, &h);
1737 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1738
2b5f62a0
VZ
1739 return w;
1740#else
2b77c3fc 1741 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
83df96d6 1742
3cd0b8c5
RR
1743 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1744
1745 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1746
1747 int direction, ascent, descent;
1748 XCharStruct overall;
ab9d0a8c 1749
3cd0b8c5 1750 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1751
3cd0b8c5 1752 return (wxCoord)(overall.width / m_scaleX);
2b5f62a0 1753#endif
83df96d6
JS
1754}
1755
2b77c3fc 1756wxCoord wxWindowDCImpl::GetCharHeight() const
83df96d6 1757{
2b77c3fc 1758 wxCHECK_MSG( IsOk(), 0, wxT("invalid dc") );
ab9d0a8c 1759
2b5f62a0
VZ
1760#if wxUSE_UNICODE
1761 PangoLayout *layout = pango_layout_new( m_context );
ab9d0a8c 1762
e66faf3d 1763 if (m_fontdesc)
670f9935 1764 pango_layout_set_font_description(layout, m_fontdesc);
e66faf3d 1765 else
670f9935
WS
1766 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1767
2b5f62a0
VZ
1768 pango_layout_set_text(layout, "H", 1 );
1769 int w,h;
1770 pango_layout_get_pixel_size(layout, &w, &h);
1771 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1772
2b5f62a0
VZ
1773 return h;
1774#else
2b77c3fc 1775 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
83df96d6 1776
3cd0b8c5
RR
1777 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1778
1779 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1780
1781 int direction, ascent, descent;
1782 XCharStruct overall;
ab9d0a8c 1783
3cd0b8c5 1784 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1785
3cd0b8c5 1786 return (wxCoord)((ascent+descent) / m_scaleY);
2b5f62a0 1787#endif
83df96d6
JS
1788}
1789
2b77c3fc 1790void wxWindowDCImpl::Clear()
83df96d6 1791{
2b77c3fc 1792 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1793
2b77c3fc 1794 if (!m_x11window) return;
83df96d6 1795
3cd0b8c5
RR
1796 /* - we either are a memory dc or have a window as the
1797 owner. anything else shouldn't happen.
1798 - we don't use gdk_window_clear() as we don't set
1799 the window's background colour anymore. it is too
1800 much pain to keep the DC's and the window's back-
1801 ground colour in synch. */
83df96d6 1802
2b77c3fc 1803 if (m_window)
3cd0b8c5
RR
1804 {
1805 int width,height;
2b77c3fc
RR
1806 m_window->GetSize( &width, &height );
1807 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
3cd0b8c5
RR
1808 return;
1809 }
83df96d6 1810
3cd0b8c5
RR
1811 if (m_isMemDC)
1812 {
1813 int width,height;
2b77c3fc
RR
1814 DoGetSize( &width, &height );
1815 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
3cd0b8c5
RR
1816 return;
1817 }
83df96d6
JS
1818}
1819
2b77c3fc 1820void wxWindowDCImpl::SetFont( const wxFont &font )
83df96d6 1821{
2b77c3fc 1822 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6
JS
1823
1824 m_font = font;
670f9935 1825
1175aa4e 1826#if wxUSE_UNICODE
e66faf3d 1827 m_fontdesc = font.GetNativeFontInfo()->description;
1175aa4e 1828#endif
83df96d6
JS
1829}
1830
2b77c3fc 1831void wxWindowDCImpl::SetPen( const wxPen &pen )
83df96d6 1832{
2b77c3fc 1833 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
3cd0b8c5
RR
1834
1835 if (m_pen == pen) return;
83df96d6
JS
1836
1837 m_pen = pen;
83df96d6 1838
2b77c3fc 1839 if (!m_pen.IsOk()) return;
83df96d6 1840
2b77c3fc 1841 if (!m_x11window) return;
83df96d6 1842
3cd0b8c5
RR
1843 int width = m_pen.GetWidth();
1844 if (width <= 0)
1845 {
1846 // CMB: if width is non-zero scale it with the dc
1847 width = 1;
1848 }
1849 else
1850 {
1851 // X doesn't allow different width in x and y and so we take
1852 // the average
1853 double w = 0.5 +
1854 ( fabs((double) XLOG2DEVREL(width)) +
1855 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1856 width = (int)w;
1857 }
1858
1859 static const wxX11Dash dotted[] = {1, 1};
1860 static const wxX11Dash short_dashed[] = {2, 2};
1861 static const wxX11Dash long_dashed[] = {2, 4};
1862 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1863
1864 // We express dash pattern in pen width unit, so we are
1865 // independent of zoom factor and so on...
1866 int req_nb_dash;
1867 const wxX11Dash *req_dash;
1868
1869 int lineStyle = LineSolid;
1870 switch (m_pen.GetStyle())
83df96d6 1871 {
83df96d6 1872 case wxUSER_DASH:
3cd0b8c5
RR
1873 {
1874 lineStyle = LineOnOffDash;
1875 req_nb_dash = m_pen.GetDashCount();
1876 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1877 break;
3cd0b8c5 1878 }
83df96d6 1879 case wxDOT:
3cd0b8c5
RR
1880 {
1881 lineStyle = LineOnOffDash;
83df96d6
JS
1882 req_nb_dash = 2;
1883 req_dash = dotted;
83df96d6 1884 break;
3cd0b8c5 1885 }
83df96d6 1886 case wxLONG_DASH:
3cd0b8c5
RR
1887 {
1888 lineStyle = LineOnOffDash;
83df96d6
JS
1889 req_nb_dash = 2;
1890 req_dash = long_dashed;
83df96d6 1891 break;
3cd0b8c5
RR
1892 }
1893 case wxSHORT_DASH:
1894 {
1895 lineStyle = LineOnOffDash;
1896 req_nb_dash = 2;
1897 req_dash = short_dashed;
1898 break;
1899 }
83df96d6 1900 case wxDOT_DASH:
3cd0b8c5
RR
1901 {
1902// lineStyle = LineDoubleDash;
1903 lineStyle = LineOnOffDash;
83df96d6
JS
1904 req_nb_dash = 4;
1905 req_dash = dotted_dashed;
83df96d6 1906 break;
3cd0b8c5
RR
1907 }
1908
1909 case wxTRANSPARENT:
1910 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1911 case wxSTIPPLE:
1912 case wxSOLID:
83df96d6 1913 default:
3cd0b8c5
RR
1914 {
1915 lineStyle = LineSolid;
d3b9f782 1916 req_dash = NULL;
83df96d6 1917 req_nb_dash = 0;
3cd0b8c5 1918 break;
83df96d6 1919 }
3cd0b8c5 1920 }
83df96d6 1921
3cd0b8c5
RR
1922 int capStyle = CapRound;
1923 switch (m_pen.GetCap())
1924 {
1925 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1926 case wxCAP_BUTT: { capStyle = CapButt; break; }
1927 case wxCAP_ROUND:
1928 default:
83df96d6 1929 {
3cd0b8c5 1930 if (width <= 1)
83df96d6 1931 {
3cd0b8c5
RR
1932 width = 0;
1933 capStyle = CapNotLast;
83df96d6
JS
1934 }
1935 else
1936 {
3cd0b8c5 1937 capStyle = CapRound;
83df96d6 1938 }
83df96d6
JS
1939 break;
1940 }
3cd0b8c5 1941 }
83df96d6 1942
3cd0b8c5
RR
1943 int joinStyle = JoinRound;
1944 switch (m_pen.GetJoin())
1945 {
1946 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1947 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1948 case wxJOIN_ROUND:
3cd0b8c5 1949 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1950 }
1951
3cd0b8c5 1952 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1953
3cd0b8c5
RR
1954 m_pen.GetColour().CalcPixel( m_cmap );
1955 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1956}
83df96d6 1957
2b77c3fc 1958void wxWindowDCImpl::SetBrush( const wxBrush &brush )
3cd0b8c5 1959{
2b77c3fc 1960 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1961
3cd0b8c5 1962 if (m_brush == brush) return;
83df96d6 1963
3cd0b8c5
RR
1964 m_brush = brush;
1965
2b77c3fc 1966 if (!m_brush.IsOk()) return;
83df96d6 1967
2b77c3fc 1968 if (!m_x11window) return;
3cd0b8c5
RR
1969
1970 m_brush.GetColour().CalcPixel( m_cmap );
1971 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
ab9d0a8c 1972
3cd0b8c5
RR
1973 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1974
2b77c3fc 1975 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->IsOk()))
83df96d6 1976 {
3cd0b8c5 1977 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1978 {
3cd0b8c5
RR
1979 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1980 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1981 }
1982 else
1983 {
3cd0b8c5 1984 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1985 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1986 }
3cd0b8c5 1987 }
83df96d6 1988
3cd0b8c5
RR
1989 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1990 {
1991 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1992 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1993 }
83df96d6 1994
ab9d0a8c 1995 if (m_brush.IsHatch())
3cd0b8c5
RR
1996 {
1997 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1998 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1999 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
2000 }
83df96d6
JS
2001}
2002
2b77c3fc 2003void wxWindowDCImpl::SetBackground( const wxBrush &brush )
83df96d6 2004{
3cd0b8c5
RR
2005 /* CMB 21/7/98: Added SetBackground. Sets background brush
2006 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 2007
2b77c3fc 2008 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2009
3cd0b8c5 2010 if (m_backgroundBrush == brush) return;
83df96d6 2011
3cd0b8c5 2012 m_backgroundBrush = brush;
83df96d6 2013
2b77c3fc 2014 if (!m_backgroundBrush.IsOk()) return;
83df96d6 2015
2b77c3fc 2016 if (!m_x11window) return;
83df96d6 2017
3cd0b8c5
RR
2018 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
2019 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
2020 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
2021 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
2022 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 2023
3cd0b8c5 2024 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 2025
2b77c3fc 2026 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->IsOk()))
83df96d6 2027 {
3cd0b8c5 2028 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 2029 {
3cd0b8c5
RR
2030 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
2031 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 2032 }
3cd0b8c5 2033 else
83df96d6 2034 {
3cd0b8c5 2035 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 2036 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 2037 }
83df96d6
JS
2038 }
2039
ab9d0a8c 2040 if (m_backgroundBrush.IsHatch())
83df96d6 2041 {
3cd0b8c5
RR
2042 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
2043 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
2044 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 2045 }
83df96d6
JS
2046}
2047
89efaf2b 2048void wxWindowDCImpl::SetLogicalFunction( wxRasterOperationMode function )
83df96d6 2049{
2b77c3fc 2050 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6
JS
2051
2052 int x_function;
2053
83df96d6
JS
2054 if (m_logicalFunction == function)
2055 return;
2056
3cd0b8c5 2057 // VZ: shouldn't this be a CHECK?
2b77c3fc 2058 if (!m_x11window)
3cd0b8c5 2059 return;
ab9d0a8c 2060
83df96d6
JS
2061 switch (function)
2062 {
2063 case wxCLEAR:
2064 x_function = GXclear;
2065 break;
2066 case wxXOR:
2067 x_function = GXxor;
2068 break;
2069 case wxINVERT:
2070 x_function = GXinvert;
2071 break;
2072 case wxOR_REVERSE:
2073 x_function = GXorReverse;
2074 break;
2075 case wxAND_REVERSE:
2076 x_function = GXandReverse;
2077 break;
2078 case wxAND:
2079 x_function = GXand;
2080 break;
2081 case wxOR:
2082 x_function = GXor;
2083 break;
2084 case wxAND_INVERT:
2085 x_function = GXandInverted;
2086 break;
2087 case wxNO_OP:
2088 x_function = GXnoop;
2089 break;
2090 case wxNOR:
2091 x_function = GXnor;
2092 break;
2093 case wxEQUIV:
2094 x_function = GXequiv;
2095 break;
2096 case wxSRC_INVERT:
2097 x_function = GXcopyInverted;
2098 break;
2099 case wxOR_INVERT:
2100 x_function = GXorInverted;
2101 break;
2102 case wxNAND:
2103 x_function = GXnand;
2104 break;
2105 case wxSET:
2106 x_function = GXset;
2107 break;
2108 case wxCOPY:
2109 default:
2110 x_function = GXcopy;
2111 break;
2112 }
2113
3cd0b8c5
RR
2114 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2115 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 2116
3cd0b8c5
RR
2117 // to stay compatible with wxMSW, we don't apply ROPs to the text
2118 // operations (i.e. DrawText/DrawRotatedText).
2119 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2120 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
ab9d0a8c 2121
83df96d6 2122 m_logicalFunction = function;
83df96d6
JS
2123}
2124
2b77c3fc 2125void wxWindowDCImpl::SetTextForeground( const wxColour &col )
83df96d6 2126{
2b77c3fc 2127 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2128
3cd0b8c5
RR
2129 // don't set m_textForegroundColour to an invalid colour as we'd crash
2130 // later then (we use m_textForegroundColour.GetColor() without checking
2131 // in a few places)
2b77c3fc 2132 if ( !col.IsOk() || (m_textForegroundColour == col) )
83df96d6
JS
2133 return;
2134
2135 m_textForegroundColour = col;
2136
2b77c3fc 2137 if (m_x11window)
3cd0b8c5
RR
2138 {
2139 m_textForegroundColour.CalcPixel( m_cmap );
2140 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2141 }
83df96d6
JS
2142}
2143
2b77c3fc 2144void wxWindowDCImpl::SetTextBackground( const wxColour &col )
83df96d6 2145{
2b77c3fc 2146 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2147
3cd0b8c5 2148 // same as above
2b77c3fc 2149 if ( !col.IsOk() || (m_textBackgroundColour == col) )
83df96d6
JS
2150 return;
2151
2152 m_textBackgroundColour = col;
3cd0b8c5 2153
2b77c3fc 2154 if (m_x11window)
3cd0b8c5
RR
2155 {
2156 m_textBackgroundColour.CalcPixel( m_cmap );
2157 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2158 }
83df96d6
JS
2159}
2160
2b77c3fc 2161void wxWindowDCImpl::SetBackgroundMode( int mode )
83df96d6 2162{
2b77c3fc 2163 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
3cd0b8c5 2164
83df96d6 2165 m_backgroundMode = mode;
3cd0b8c5 2166
0b5c0e1a
JS
2167#if wxUSE_NANOX
2168 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2169#endif
2170
2b77c3fc 2171 if (!m_x11window) return;
3cd0b8c5
RR
2172
2173 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2174 // transparent/solid background mode
2175
2176 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2177 {
2178 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2179 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2180 }
83df96d6
JS
2181}
2182
2b77c3fc 2183void wxWindowDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) )
83df96d6 2184{
3cd0b8c5 2185#if 0
2b77c3fc 2186 if (m_x11window)
83df96d6 2187 {
2b77c3fc 2188 if (palette.IsOk())
83df96d6 2189 /* Use GetXColormap */
2b77c3fc 2190 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
83df96d6
JS
2191 (Colormap) palette.GetXColormap());
2192 else
2193 /* Use wxGetMainColormap */
2b77c3fc 2194 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
83df96d6
JS
2195 (Colormap) wxTheApp->GetMainColormap(m_display));
2196 }
3cd0b8c5 2197#endif
83df96d6
JS
2198}
2199
2b77c3fc 2200void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 2201{
2b77c3fc 2202 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2203
2b77c3fc 2204 if (!m_x11window) return;
83df96d6 2205
41e52241
JS
2206 if (width <= 0)
2207 width = 1;
2208
2209 if (height <= 0)
2210 height = 1;
2211
3cd0b8c5
RR
2212 wxRect rect;
2213 rect.x = XLOG2DEV(x);
2214 rect.y = YLOG2DEV(y);
2215 rect.width = XLOG2DEVREL(width);
2216 rect.height = YLOG2DEVREL(height);
2217
6dd25d20 2218 if (!m_currentClippingRegion.IsEmpty())
3cd0b8c5 2219 m_currentClippingRegion.Intersect( rect );
83df96d6 2220 else
6dd25d20 2221 m_currentClippingRegion = rect;
3cd0b8c5
RR
2222
2223#if USE_PAINT_REGION
6dd25d20 2224 if (!m_paintClippingRegion.IsEmpty())
3cd0b8c5
RR
2225 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2226#endif
2227
2228 wxCoord xx, yy, ww, hh;
2229 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
f95b06a6 2230 wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh );
3cd0b8c5
RR
2231
2232 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2233 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2234 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2235 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2236}
83df96d6 2237
fdaad94e 2238void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion& region )
3cd0b8c5 2239{
2b77c3fc 2240 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2241
3cd0b8c5 2242 if (region.Empty())
83df96d6 2243 {
3cd0b8c5
RR
2244 DestroyClippingRegion();
2245 return;
83df96d6 2246 }
3cd0b8c5 2247
2b77c3fc 2248 if (!m_x11window) return;
3cd0b8c5 2249
6dd25d20 2250 if (!m_currentClippingRegion.IsEmpty())
3cd0b8c5 2251 m_currentClippingRegion.Intersect( region );
83df96d6 2252 else
6dd25d20 2253 m_currentClippingRegion = region;
83df96d6 2254
3cd0b8c5 2255#if USE_PAINT_REGION
6dd25d20 2256 if (!m_paintClippingRegion.IsEmpty())
3cd0b8c5
RR
2257 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2258#endif
83df96d6 2259
3cd0b8c5
RR
2260 wxCoord xx, yy, ww, hh;
2261 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
f95b06a6 2262 wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh );
3cd0b8c5
RR
2263
2264 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2265 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2266 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2267 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
2268}
2269
2b77c3fc 2270void wxWindowDCImpl::DestroyClippingRegion()
83df96d6 2271{
2b77c3fc 2272 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2273
2b77c3fc 2274 wxDCImpl::DestroyClippingRegion();
83df96d6 2275
3cd0b8c5 2276 m_currentClippingRegion.Clear();
83df96d6 2277
3cd0b8c5
RR
2278#if USE_PAINT_REGION
2279 if (!m_paintClippingRegion.IsEmpty())
2280 m_currentClippingRegion.Union( m_paintClippingRegion );
2281#endif
83df96d6 2282
2b77c3fc 2283 if (!m_x11window) return;
83df96d6 2284
3cd0b8c5
RR
2285 if (m_currentClippingRegion.IsEmpty())
2286 {
2287 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2288 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2289 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2290 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2291 }
2292 else
2293 {
2294 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2295 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2296 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2297 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2298 }
2299}
83df96d6 2300
2b77c3fc 2301void wxWindowDCImpl::Destroy()
83df96d6 2302{
3cd0b8c5
RR
2303 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2304 m_penGC = NULL;
2305 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2306 m_brushGC = NULL;
2307 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2308 m_textGC = NULL;
2309 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2310 m_bgGC = NULL;
2311}
83df96d6 2312
2b77c3fc 2313void wxWindowDCImpl::ComputeScaleAndOrigin()
3cd0b8c5
RR
2314{
2315 /* CMB: copy scale to see if it changes */
2316 double origScaleX = m_scaleX;
2317 double origScaleY = m_scaleY;
83df96d6 2318
2b77c3fc 2319 wxDCImpl::ComputeScaleAndOrigin();
83df96d6 2320
3cd0b8c5
RR
2321 /* CMB: if scale has changed call SetPen to recalulate the line width */
2322 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2b77c3fc 2323 (m_pen.IsOk()))
3cd0b8c5
RR
2324 {
2325 /* this is a bit artificial, but we need to force wxDC to think
2326 the pen has changed */
2327 wxPen pen = m_pen;
2328 m_pen = wxNullPen;
2329 SetPen( pen );
2330 }
83df96d6
JS
2331}
2332
2b77c3fc 2333wxSize wxWindowDCImpl::GetPPI() const
83df96d6
JS
2334{
2335 return wxSize(100, 100);
2336}
2337
2b77c3fc 2338int wxWindowDCImpl::GetDepth() const
83df96d6 2339{
3cd0b8c5 2340 wxFAIL_MSG(wxT("not implemented"));
83df96d6 2341
3cd0b8c5
RR
2342 return -1;
2343}
83df96d6 2344
3cd0b8c5
RR
2345//-----------------------------------------------------------------------------
2346// wxClientDC
2347//-----------------------------------------------------------------------------
2348
03580f20 2349IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
3cd0b8c5 2350
2b77c3fc
RR
2351wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window )
2352 : wxWindowDCImpl( owner, window )
83df96d6 2353{
ab6b6b15 2354 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
ab9d0a8c 2355
2b77c3fc 2356 m_x11window = (WXWindow*) window->GetClientAreaWindow();
ab9d0a8c 2357
2b5f62a0 2358 // Adjust the client area when the wxWindow is not using 2 X11 windows.
2b77c3fc 2359 if (m_x11window == (WXWindow*) window->GetMainWindow())
7948c0c2 2360 {
c2c0dabf
RR
2361 wxPoint ptOrigin = window->GetClientAreaOrigin();
2362 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2363 wxSize size = window->GetClientSize();
2b77c3fc 2364 DoSetClippingRegion( 0, 0, size.x, size.y );
7948c0c2 2365 }
83df96d6
JS
2366}
2367
2b77c3fc 2368void wxClientDCImpl::DoGetSize(int *width, int *height) const
83df96d6 2369{
2b77c3fc 2370 wxCHECK_RET( m_window, _T("GetSize() doesn't work without window") );
3cd0b8c5 2371
2b77c3fc 2372 m_window->GetClientSize( width, height );
83df96d6
JS
2373}
2374
ab6b6b15
RR
2375// ----------------------------------------------------------------------------
2376// wxPaintDC
2377// ----------------------------------------------------------------------------
2378
2b77c3fc 2379IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxClientDCImpl)
ab6b6b15 2380
2b77c3fc
RR
2381wxPaintDCImpl::wxPaintDCImpl(wxDC *owner, wxWindow* window)
2382 : wxClientDCImpl(owner, window)
ab6b6b15
RR
2383{
2384#if USE_PAINT_REGION
2385 if (!window->GetClipPaintRegion())
2386 return;
2387
2388 m_paintClippingRegion = window->GetUpdateRegion();
2389 Region region = (Region) m_paintClippingRegion.GetX11Region();
2390 if (region)
2391 {
2392 m_currentClippingRegion.Union( m_paintClippingRegion );
2393
2394 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2395 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2396 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2397 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2398 }
2399#endif // USE_PAINT_REGION
2400}
2401
83df96d6 2402// ----------------------------------------------------------------------------
3cd0b8c5 2403// wxDCModule
83df96d6
JS
2404// ----------------------------------------------------------------------------
2405
3cd0b8c5 2406class wxDCModule : public wxModule
83df96d6 2407{
3cd0b8c5 2408public:
b886fae6
VZ
2409 // we must be cleaned up before wxDisplayModule which closes the global
2410 // display
2411 wxDCModule()
2412 {
2413 AddDependency(wxClassInfo::FindClass(_T("wxX11DisplayModule")));
2414 }
2415
2416 bool OnInit() { wxInitGCPool(); return true; }
2417 void OnExit() { wxCleanUpGCPool(); }
83df96d6 2418
3cd0b8c5
RR
2419private:
2420 DECLARE_DYNAMIC_CLASS(wxDCModule)
2421};
83df96d6 2422
3cd0b8c5 2423IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 2424