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