]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
add support for alpha in color dialog on OSX, see #14127
[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
679918f9 186 m_x11window = (WXWindow*) window->X11GetMainWindow();
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{
9a83f860 348 wxCHECK_RET( m_window, wxT("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
4787c92d 624void wxWindowDCImpl::DoDrawLines( int n, const 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
4787c92d 644void wxWindowDCImpl::DoDrawPolygon( int n, const 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,
03647350 1294 wxDC *source, wxCoord xsrc, wxCoord ysrc,
89efaf2b 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
0b2a860f 1573 const wxScopedCharBuffer data(text.utf8_str());
02e26099 1574 pango_layout_set_text(layout, data, data.length());
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{
5f480c0b
VZ
1661 // Do not test for DC validity here, querying text extents is supposed to
1662 // work even with a non-initialized wxMemoryDC. And the code below does
1663 // actually work in this case.
83df96d6 1664
ab9d0a8c 1665 if (string.empty())
2b5f62a0
VZ
1666 {
1667 if (width) (*width) = 0;
1668 if (height) (*height) = 0;
1669 return;
1670 }
ab9d0a8c 1671
2b5f62a0
VZ
1672#if wxUSE_UNICODE
1673 PangoLayout *layout = pango_layout_new( m_context );
1674
1675 if (font)
1676 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
1677 else
1678 pango_layout_set_font_description(layout, m_fontdesc);
ab9d0a8c 1679
0b2a860f 1680 const wxScopedCharBuffer data(string.utf8_str());
02e26099 1681 pango_layout_set_text(layout, data, data.length());
ab9d0a8c 1682
2b5f62a0
VZ
1683 // Measure text.
1684 int w,h;
1685 pango_layout_get_pixel_size(layout, &w, &h);
ab9d0a8c
WS
1686
1687 if (width) (*width) = (wxCoord) w;
2b5f62a0
VZ
1688 if (height) (*height) = (wxCoord) h;
1689 if (descent)
1690 {
1691 // Do something about metrics here. TODO.
1692 (*descent) = 0;
1693 }
1694 if (externalLeading) (*externalLeading) = 0; // ??
ab9d0a8c 1695
2b5f62a0
VZ
1696 g_object_unref( G_OBJECT( layout ) );
1697#else
3cd0b8c5
RR
1698 wxFont fontToUse = m_font;
1699 if (font) fontToUse = *font;
83df96d6 1700
2b77c3fc 1701 wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") );
83df96d6 1702
3cd0b8c5 1703 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1704
3cd0b8c5 1705 wxCHECK_RET( xfont, wxT("invalid font") );
ab9d0a8c 1706
83df96d6
JS
1707 int direction, ascent, descent2;
1708 XCharStruct overall;
83df96d6 1709
3ad2d972 1710 XTextExtents( xfont, (const char*) string.c_str(), string.length(), &direction,
83df96d6
JS
1711 &ascent, &descent2, &overall);
1712
3cd0b8c5
RR
1713 if (width)
1714 *width = (wxCoord)( overall.width / m_scaleX );
1715 if (height)
1716 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1717 if (descent)
3cd0b8c5 1718 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1719 if (externalLeading)
3cd0b8c5 1720 *externalLeading = 0; // ??
2b5f62a0 1721#endif
83df96d6
JS
1722}
1723
2b77c3fc 1724wxCoord wxWindowDCImpl::GetCharWidth() const
83df96d6 1725{
5f480c0b
VZ
1726 // Do not test for DC validity here for the same reasons as in
1727 // DoGetTextExtent() above.
ab9d0a8c 1728
2b5f62a0
VZ
1729#if wxUSE_UNICODE
1730 PangoLayout *layout = pango_layout_new( m_context );
ab9d0a8c 1731
e66faf3d 1732 if (m_fontdesc)
670f9935 1733 pango_layout_set_font_description(layout, m_fontdesc);
e66faf3d 1734 else
670f9935
WS
1735 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1736
2b5f62a0
VZ
1737 pango_layout_set_text(layout, "H", 1 );
1738 int w,h;
1739 pango_layout_get_pixel_size(layout, &w, &h);
1740 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1741
2b5f62a0
VZ
1742 return w;
1743#else
2b77c3fc 1744 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
83df96d6 1745
3cd0b8c5
RR
1746 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1747
1748 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1749
1750 int direction, ascent, descent;
1751 XCharStruct overall;
ab9d0a8c 1752
3cd0b8c5 1753 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1754
3cd0b8c5 1755 return (wxCoord)(overall.width / m_scaleX);
2b5f62a0 1756#endif
83df96d6
JS
1757}
1758
2b77c3fc 1759wxCoord wxWindowDCImpl::GetCharHeight() const
83df96d6 1760{
5f480c0b
VZ
1761 // Do not test for DC validity here for the same reasons as in
1762 // DoGetTextExtent() above.
ab9d0a8c 1763
2b5f62a0
VZ
1764#if wxUSE_UNICODE
1765 PangoLayout *layout = pango_layout_new( m_context );
ab9d0a8c 1766
e66faf3d 1767 if (m_fontdesc)
670f9935 1768 pango_layout_set_font_description(layout, m_fontdesc);
e66faf3d 1769 else
670f9935
WS
1770 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1771
2b5f62a0
VZ
1772 pango_layout_set_text(layout, "H", 1 );
1773 int w,h;
1774 pango_layout_get_pixel_size(layout, &w, &h);
1775 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1776
2b5f62a0
VZ
1777 return h;
1778#else
2b77c3fc 1779 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
83df96d6 1780
3cd0b8c5
RR
1781 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1782
1783 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1784
1785 int direction, ascent, descent;
1786 XCharStruct overall;
ab9d0a8c 1787
3cd0b8c5 1788 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1789
3cd0b8c5 1790 return (wxCoord)((ascent+descent) / m_scaleY);
2b5f62a0 1791#endif
83df96d6
JS
1792}
1793
2b77c3fc 1794void wxWindowDCImpl::Clear()
83df96d6 1795{
2b77c3fc 1796 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1797
2b77c3fc 1798 if (!m_x11window) return;
83df96d6 1799
3cd0b8c5
RR
1800 /* - we either are a memory dc or have a window as the
1801 owner. anything else shouldn't happen.
1802 - we don't use gdk_window_clear() as we don't set
1803 the window's background colour anymore. it is too
1804 much pain to keep the DC's and the window's back-
1805 ground colour in synch. */
83df96d6 1806
2b77c3fc 1807 if (m_window)
3cd0b8c5
RR
1808 {
1809 int width,height;
2b77c3fc
RR
1810 m_window->GetSize( &width, &height );
1811 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
3cd0b8c5
RR
1812 return;
1813 }
83df96d6 1814
3cd0b8c5
RR
1815 if (m_isMemDC)
1816 {
1817 int width,height;
2b77c3fc
RR
1818 DoGetSize( &width, &height );
1819 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
3cd0b8c5
RR
1820 return;
1821 }
83df96d6
JS
1822}
1823
2b77c3fc 1824void wxWindowDCImpl::SetFont( const wxFont &font )
83df96d6 1825{
2b77c3fc 1826 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6
JS
1827
1828 m_font = font;
670f9935 1829
1175aa4e 1830#if wxUSE_UNICODE
e66faf3d 1831 m_fontdesc = font.GetNativeFontInfo()->description;
1175aa4e 1832#endif
83df96d6
JS
1833}
1834
2b77c3fc 1835void wxWindowDCImpl::SetPen( const wxPen &pen )
83df96d6 1836{
2b77c3fc 1837 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
3cd0b8c5
RR
1838
1839 if (m_pen == pen) return;
83df96d6
JS
1840
1841 m_pen = pen;
83df96d6 1842
2b77c3fc 1843 if (!m_pen.IsOk()) return;
83df96d6 1844
2b77c3fc 1845 if (!m_x11window) return;
83df96d6 1846
3cd0b8c5
RR
1847 int width = m_pen.GetWidth();
1848 if (width <= 0)
1849 {
1850 // CMB: if width is non-zero scale it with the dc
1851 width = 1;
1852 }
1853 else
1854 {
1855 // X doesn't allow different width in x and y and so we take
1856 // the average
1857 double w = 0.5 +
1858 ( fabs((double) XLOG2DEVREL(width)) +
1859 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1860 width = (int)w;
1861 }
1862
1863 static const wxX11Dash dotted[] = {1, 1};
1864 static const wxX11Dash short_dashed[] = {2, 2};
1865 static const wxX11Dash long_dashed[] = {2, 4};
1866 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1867
1868 // We express dash pattern in pen width unit, so we are
1869 // independent of zoom factor and so on...
1870 int req_nb_dash;
1871 const wxX11Dash *req_dash;
1872
1873 int lineStyle = LineSolid;
1874 switch (m_pen.GetStyle())
83df96d6 1875 {
83df96d6 1876 case wxUSER_DASH:
3cd0b8c5
RR
1877 {
1878 lineStyle = LineOnOffDash;
1879 req_nb_dash = m_pen.GetDashCount();
1880 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1881 break;
3cd0b8c5 1882 }
83df96d6 1883 case wxDOT:
3cd0b8c5
RR
1884 {
1885 lineStyle = LineOnOffDash;
83df96d6
JS
1886 req_nb_dash = 2;
1887 req_dash = dotted;
83df96d6 1888 break;
3cd0b8c5 1889 }
83df96d6 1890 case wxLONG_DASH:
3cd0b8c5
RR
1891 {
1892 lineStyle = LineOnOffDash;
83df96d6
JS
1893 req_nb_dash = 2;
1894 req_dash = long_dashed;
83df96d6 1895 break;
3cd0b8c5
RR
1896 }
1897 case wxSHORT_DASH:
1898 {
1899 lineStyle = LineOnOffDash;
1900 req_nb_dash = 2;
1901 req_dash = short_dashed;
1902 break;
1903 }
83df96d6 1904 case wxDOT_DASH:
3cd0b8c5
RR
1905 {
1906// lineStyle = LineDoubleDash;
1907 lineStyle = LineOnOffDash;
83df96d6
JS
1908 req_nb_dash = 4;
1909 req_dash = dotted_dashed;
83df96d6 1910 break;
3cd0b8c5
RR
1911 }
1912
1913 case wxTRANSPARENT:
1914 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1915 case wxSTIPPLE:
1916 case wxSOLID:
83df96d6 1917 default:
3cd0b8c5
RR
1918 {
1919 lineStyle = LineSolid;
d3b9f782 1920 req_dash = NULL;
83df96d6 1921 req_nb_dash = 0;
3cd0b8c5 1922 break;
83df96d6 1923 }
3cd0b8c5 1924 }
83df96d6 1925
3cd0b8c5
RR
1926 int capStyle = CapRound;
1927 switch (m_pen.GetCap())
1928 {
1929 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1930 case wxCAP_BUTT: { capStyle = CapButt; break; }
1931 case wxCAP_ROUND:
1932 default:
83df96d6 1933 {
3cd0b8c5 1934 if (width <= 1)
83df96d6 1935 {
3cd0b8c5
RR
1936 width = 0;
1937 capStyle = CapNotLast;
83df96d6
JS
1938 }
1939 else
1940 {
3cd0b8c5 1941 capStyle = CapRound;
83df96d6 1942 }
83df96d6
JS
1943 break;
1944 }
3cd0b8c5 1945 }
83df96d6 1946
3cd0b8c5
RR
1947 int joinStyle = JoinRound;
1948 switch (m_pen.GetJoin())
1949 {
1950 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1951 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1952 case wxJOIN_ROUND:
3cd0b8c5 1953 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1954 }
1955
3cd0b8c5 1956 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1957
3cd0b8c5
RR
1958 m_pen.GetColour().CalcPixel( m_cmap );
1959 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1960}
83df96d6 1961
2b77c3fc 1962void wxWindowDCImpl::SetBrush( const wxBrush &brush )
3cd0b8c5 1963{
2b77c3fc 1964 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 1965
3cd0b8c5 1966 if (m_brush == brush) return;
83df96d6 1967
3cd0b8c5
RR
1968 m_brush = brush;
1969
2b77c3fc 1970 if (!m_brush.IsOk()) return;
83df96d6 1971
2b77c3fc 1972 if (!m_x11window) return;
3cd0b8c5
RR
1973
1974 m_brush.GetColour().CalcPixel( m_cmap );
1975 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
ab9d0a8c 1976
3cd0b8c5
RR
1977 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1978
2b77c3fc 1979 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->IsOk()))
83df96d6 1980 {
3cd0b8c5 1981 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1982 {
3cd0b8c5
RR
1983 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1984 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1985 }
1986 else
1987 {
3cd0b8c5 1988 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1989 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1990 }
3cd0b8c5 1991 }
83df96d6 1992
3cd0b8c5
RR
1993 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1994 {
1995 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1996 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1997 }
83df96d6 1998
ab9d0a8c 1999 if (m_brush.IsHatch())
3cd0b8c5
RR
2000 {
2001 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
2002 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
2003 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
2004 }
83df96d6
JS
2005}
2006
2b77c3fc 2007void wxWindowDCImpl::SetBackground( const wxBrush &brush )
83df96d6 2008{
3cd0b8c5
RR
2009 /* CMB 21/7/98: Added SetBackground. Sets background brush
2010 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 2011
2b77c3fc 2012 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2013
3cd0b8c5 2014 if (m_backgroundBrush == brush) return;
83df96d6 2015
3cd0b8c5 2016 m_backgroundBrush = brush;
83df96d6 2017
2b77c3fc 2018 if (!m_backgroundBrush.IsOk()) return;
83df96d6 2019
2b77c3fc 2020 if (!m_x11window) return;
83df96d6 2021
3cd0b8c5
RR
2022 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
2023 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
2024 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
2025 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
2026 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 2027
3cd0b8c5 2028 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 2029
2b77c3fc 2030 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->IsOk()))
83df96d6 2031 {
3cd0b8c5 2032 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 2033 {
3cd0b8c5
RR
2034 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
2035 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 2036 }
3cd0b8c5 2037 else
83df96d6 2038 {
3cd0b8c5 2039 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 2040 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 2041 }
83df96d6
JS
2042 }
2043
ab9d0a8c 2044 if (m_backgroundBrush.IsHatch())
83df96d6 2045 {
3cd0b8c5
RR
2046 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
2047 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
2048 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 2049 }
83df96d6
JS
2050}
2051
89efaf2b 2052void wxWindowDCImpl::SetLogicalFunction( wxRasterOperationMode function )
83df96d6 2053{
2b77c3fc 2054 wxCHECK_RET( IsOk(), wxT("invalid dc") );
83df96d6
JS
2055
2056 int x_function;
2057
83df96d6
JS
2058 if (m_logicalFunction == function)
2059 return;
2060
3cd0b8c5 2061 // VZ: shouldn't this be a CHECK?
2b77c3fc 2062 if (!m_x11window)
3cd0b8c5 2063 return;
ab9d0a8c 2064
83df96d6
JS
2065 switch (function)
2066 {
2067 case wxCLEAR:
2068 x_function = GXclear;
2069 break;
2070 case wxXOR:
2071 x_function = GXxor;
2072 break;
2073 case wxINVERT:
2074 x_function = GXinvert;
2075 break;
2076 case wxOR_REVERSE:
2077 x_function = GXorReverse;
2078 break;
2079 case wxAND_REVERSE:
2080 x_function = GXandReverse;
2081 break;
2082 case wxAND:
2083 x_function = GXand;
2084 break;
2085 case wxOR:
2086 x_function = GXor;
2087 break;
2088 case wxAND_INVERT:
2089 x_function = GXandInverted;
2090 break;
2091 case wxNO_OP:
2092 x_function = GXnoop;
2093 break;
2094 case wxNOR:
2095 x_function = GXnor;
2096 break;
2097 case wxEQUIV:
2098 x_function = GXequiv;
2099 break;
2100 case wxSRC_INVERT:
2101 x_function = GXcopyInverted;
2102 break;
2103 case wxOR_INVERT:
2104 x_function = GXorInverted;
2105 break;
2106 case wxNAND:
2107 x_function = GXnand;
2108 break;
2109 case wxSET:
2110 x_function = GXset;
2111 break;
2112 case wxCOPY:
2113 default:
2114 x_function = GXcopy;
2115 break;
2116 }
2117
3cd0b8c5
RR
2118 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2119 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 2120
3cd0b8c5
RR
2121 // to stay compatible with wxMSW, we don't apply ROPs to the text
2122 // operations (i.e. DrawText/DrawRotatedText).
2123 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2124 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
ab9d0a8c 2125
83df96d6 2126 m_logicalFunction = function;
83df96d6
JS
2127}
2128
2b77c3fc 2129void wxWindowDCImpl::SetTextForeground( const wxColour &col )
83df96d6 2130{
2b77c3fc 2131 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2132
3cd0b8c5
RR
2133 // don't set m_textForegroundColour to an invalid colour as we'd crash
2134 // later then (we use m_textForegroundColour.GetColor() without checking
2135 // in a few places)
2b77c3fc 2136 if ( !col.IsOk() || (m_textForegroundColour == col) )
83df96d6
JS
2137 return;
2138
2139 m_textForegroundColour = col;
2140
2b77c3fc 2141 if (m_x11window)
3cd0b8c5
RR
2142 {
2143 m_textForegroundColour.CalcPixel( m_cmap );
2144 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2145 }
83df96d6
JS
2146}
2147
2b77c3fc 2148void wxWindowDCImpl::SetTextBackground( const wxColour &col )
83df96d6 2149{
2b77c3fc 2150 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2151
3cd0b8c5 2152 // same as above
2b77c3fc 2153 if ( !col.IsOk() || (m_textBackgroundColour == col) )
83df96d6
JS
2154 return;
2155
2156 m_textBackgroundColour = col;
3cd0b8c5 2157
2b77c3fc 2158 if (m_x11window)
3cd0b8c5
RR
2159 {
2160 m_textBackgroundColour.CalcPixel( m_cmap );
2161 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2162 }
83df96d6
JS
2163}
2164
2b77c3fc 2165void wxWindowDCImpl::SetBackgroundMode( int mode )
83df96d6 2166{
2b77c3fc 2167 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
3cd0b8c5 2168
83df96d6 2169 m_backgroundMode = mode;
3cd0b8c5 2170
0b5c0e1a
JS
2171#if wxUSE_NANOX
2172 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2173#endif
2174
2b77c3fc 2175 if (!m_x11window) return;
3cd0b8c5
RR
2176
2177 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2178 // transparent/solid background mode
2179
2180 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2181 {
2182 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2183 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2184 }
83df96d6
JS
2185}
2186
2b77c3fc 2187void wxWindowDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) )
83df96d6 2188{
3cd0b8c5 2189#if 0
2b77c3fc 2190 if (m_x11window)
83df96d6 2191 {
2b77c3fc 2192 if (palette.IsOk())
83df96d6 2193 /* Use GetXColormap */
2b77c3fc 2194 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
83df96d6
JS
2195 (Colormap) palette.GetXColormap());
2196 else
2197 /* Use wxGetMainColormap */
2b77c3fc 2198 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
83df96d6
JS
2199 (Colormap) wxTheApp->GetMainColormap(m_display));
2200 }
3cd0b8c5 2201#endif
83df96d6
JS
2202}
2203
2b77c3fc 2204void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 2205{
2b77c3fc 2206 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2207
2b77c3fc 2208 if (!m_x11window) return;
83df96d6 2209
41e52241
JS
2210 if (width <= 0)
2211 width = 1;
2212
2213 if (height <= 0)
2214 height = 1;
2215
3cd0b8c5
RR
2216 wxRect rect;
2217 rect.x = XLOG2DEV(x);
2218 rect.y = YLOG2DEV(y);
2219 rect.width = XLOG2DEVREL(width);
2220 rect.height = YLOG2DEVREL(height);
2221
6dd25d20 2222 if (!m_currentClippingRegion.IsEmpty())
3cd0b8c5 2223 m_currentClippingRegion.Intersect( rect );
83df96d6 2224 else
6dd25d20 2225 m_currentClippingRegion = rect;
3cd0b8c5
RR
2226
2227#if USE_PAINT_REGION
6dd25d20 2228 if (!m_paintClippingRegion.IsEmpty())
3cd0b8c5
RR
2229 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2230#endif
2231
2232 wxCoord xx, yy, ww, hh;
2233 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
f95b06a6 2234 wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh );
3cd0b8c5
RR
2235
2236 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2237 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2238 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2239 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2240}
83df96d6 2241
fdaad94e 2242void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion& region )
3cd0b8c5 2243{
2b77c3fc 2244 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2245
3cd0b8c5 2246 if (region.Empty())
83df96d6 2247 {
3cd0b8c5
RR
2248 DestroyClippingRegion();
2249 return;
83df96d6 2250 }
3cd0b8c5 2251
2b77c3fc 2252 if (!m_x11window) return;
3cd0b8c5 2253
6dd25d20 2254 if (!m_currentClippingRegion.IsEmpty())
3cd0b8c5 2255 m_currentClippingRegion.Intersect( region );
83df96d6 2256 else
6dd25d20 2257 m_currentClippingRegion = region;
83df96d6 2258
3cd0b8c5 2259#if USE_PAINT_REGION
6dd25d20 2260 if (!m_paintClippingRegion.IsEmpty())
3cd0b8c5
RR
2261 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2262#endif
83df96d6 2263
3cd0b8c5
RR
2264 wxCoord xx, yy, ww, hh;
2265 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
f95b06a6 2266 wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh );
3cd0b8c5
RR
2267
2268 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2269 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2270 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2271 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
2272}
2273
2b77c3fc 2274void wxWindowDCImpl::DestroyClippingRegion()
83df96d6 2275{
2b77c3fc 2276 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
83df96d6 2277
2b77c3fc 2278 wxDCImpl::DestroyClippingRegion();
83df96d6 2279
3cd0b8c5 2280 m_currentClippingRegion.Clear();
83df96d6 2281
3cd0b8c5
RR
2282#if USE_PAINT_REGION
2283 if (!m_paintClippingRegion.IsEmpty())
2284 m_currentClippingRegion.Union( m_paintClippingRegion );
2285#endif
83df96d6 2286
2b77c3fc 2287 if (!m_x11window) return;
83df96d6 2288
3cd0b8c5
RR
2289 if (m_currentClippingRegion.IsEmpty())
2290 {
2291 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2292 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2293 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2294 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2295 }
2296 else
2297 {
2298 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2299 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2300 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2301 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2302 }
2303}
83df96d6 2304
2b77c3fc 2305void wxWindowDCImpl::Destroy()
83df96d6 2306{
3cd0b8c5
RR
2307 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2308 m_penGC = NULL;
2309 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2310 m_brushGC = NULL;
2311 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2312 m_textGC = NULL;
2313 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2314 m_bgGC = NULL;
2315}
83df96d6 2316
2b77c3fc 2317void wxWindowDCImpl::ComputeScaleAndOrigin()
3cd0b8c5
RR
2318{
2319 /* CMB: copy scale to see if it changes */
2320 double origScaleX = m_scaleX;
2321 double origScaleY = m_scaleY;
83df96d6 2322
2b77c3fc 2323 wxDCImpl::ComputeScaleAndOrigin();
83df96d6 2324
3cd0b8c5
RR
2325 /* CMB: if scale has changed call SetPen to recalulate the line width */
2326 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2b77c3fc 2327 (m_pen.IsOk()))
3cd0b8c5
RR
2328 {
2329 /* this is a bit artificial, but we need to force wxDC to think
2330 the pen has changed */
2331 wxPen pen = m_pen;
2332 m_pen = wxNullPen;
2333 SetPen( pen );
2334 }
83df96d6
JS
2335}
2336
2b77c3fc 2337wxSize wxWindowDCImpl::GetPPI() const
83df96d6
JS
2338{
2339 return wxSize(100, 100);
2340}
2341
2b77c3fc 2342int wxWindowDCImpl::GetDepth() const
83df96d6 2343{
3cd0b8c5 2344 wxFAIL_MSG(wxT("not implemented"));
83df96d6 2345
3cd0b8c5
RR
2346 return -1;
2347}
83df96d6 2348
3cd0b8c5
RR
2349//-----------------------------------------------------------------------------
2350// wxClientDC
2351//-----------------------------------------------------------------------------
2352
03580f20 2353IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
3cd0b8c5 2354
2b77c3fc
RR
2355wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window )
2356 : wxWindowDCImpl( owner, window )
83df96d6 2357{
9a83f860 2358 wxCHECK_RET( window, wxT("NULL window in wxClientDC::wxClientDC") );
ab9d0a8c 2359
2b77c3fc 2360 m_x11window = (WXWindow*) window->GetClientAreaWindow();
ab9d0a8c 2361
2b5f62a0 2362 // Adjust the client area when the wxWindow is not using 2 X11 windows.
679918f9 2363 if (m_x11window == (WXWindow*) window->X11GetMainWindow())
7948c0c2 2364 {
c2c0dabf
RR
2365 wxPoint ptOrigin = window->GetClientAreaOrigin();
2366 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2367 wxSize size = window->GetClientSize();
2b77c3fc 2368 DoSetClippingRegion( 0, 0, size.x, size.y );
7948c0c2 2369 }
83df96d6
JS
2370}
2371
2b77c3fc 2372void wxClientDCImpl::DoGetSize(int *width, int *height) const
83df96d6 2373{
9a83f860 2374 wxCHECK_RET( m_window, wxT("GetSize() doesn't work without window") );
3cd0b8c5 2375
2b77c3fc 2376 m_window->GetClientSize( width, height );
83df96d6
JS
2377}
2378
ab6b6b15
RR
2379// ----------------------------------------------------------------------------
2380// wxPaintDC
2381// ----------------------------------------------------------------------------
2382
2b77c3fc 2383IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxClientDCImpl)
ab6b6b15 2384
2b77c3fc
RR
2385wxPaintDCImpl::wxPaintDCImpl(wxDC *owner, wxWindow* window)
2386 : wxClientDCImpl(owner, window)
ab6b6b15
RR
2387{
2388#if USE_PAINT_REGION
2389 if (!window->GetClipPaintRegion())
2390 return;
2391
2392 m_paintClippingRegion = window->GetUpdateRegion();
2393 Region region = (Region) m_paintClippingRegion.GetX11Region();
2394 if (region)
2395 {
2396 m_currentClippingRegion.Union( m_paintClippingRegion );
2397
2398 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2399 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2400 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2401 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2402 }
2403#endif // USE_PAINT_REGION
2404}
2405
83df96d6 2406// ----------------------------------------------------------------------------
3cd0b8c5 2407// wxDCModule
83df96d6
JS
2408// ----------------------------------------------------------------------------
2409
3cd0b8c5 2410class wxDCModule : public wxModule
83df96d6 2411{
3cd0b8c5 2412public:
b886fae6
VZ
2413 // we must be cleaned up before wxDisplayModule which closes the global
2414 // display
2415 wxDCModule()
2416 {
9a83f860 2417 AddDependency(wxClassInfo::FindClass(wxT("wxX11DisplayModule")));
b886fae6
VZ
2418 }
2419
2420 bool OnInit() { wxInitGCPool(); return true; }
2421 void OnExit() { wxCleanUpGCPool(); }
83df96d6 2422
3cd0b8c5
RR
2423private:
2424 DECLARE_DYNAMIC_CLASS(wxDCModule)
2425};
83df96d6 2426
3cd0b8c5 2427IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 2428