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