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