]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
Darwin dlopen functions is needed both for DYNLIB_CLASS and DYNAMIC_LOADER
[wxWidgets.git] / src / x11 / dcclient.cpp
CommitLineData
83df96d6 1/////////////////////////////////////////////////////////////////////////////
3cd0b8c5 2// Name: 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
83df96d6
JS
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
83df96d6
JS
12#ifdef __GNUG__
13 #pragma implementation "dcclient.h"
14#endif
15
16#include "wx/dcclient.h"
17#include "wx/dcmemory.h"
18#include "wx/window.h"
19#include "wx/app.h"
20#include "wx/image.h"
21
3cd0b8c5
RR
22#include "wx/x11/private.h"
23
83df96d6
JS
24#include <math.h>
25
3cd0b8c5
RR
26//-----------------------------------------------------------------------------
27// local defines
28//-----------------------------------------------------------------------------
83df96d6 29
3cd0b8c5 30#define USE_PAINT_REGION 1
83df96d6 31
3cd0b8c5
RR
32//-----------------------------------------------------------------------------
33// local data
34//-----------------------------------------------------------------------------
83df96d6
JS
35
36#include "bdiag.xbm"
37#include "fdiag.xbm"
38#include "cdiag.xbm"
39#include "horiz.xbm"
40#include "verti.xbm"
41#include "cross.xbm"
3cd0b8c5 42#define num_hatches 6
83df96d6 43
3cd0b8c5
RR
44#define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
45#define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
83df96d6 46
3cd0b8c5
RR
47static Pixmap hatches[num_hatches];
48static Pixmap *hatch_bitmap = (Pixmap *) NULL;
49
50//-----------------------------------------------------------------------------
83df96d6 51// constants
3cd0b8c5 52//-----------------------------------------------------------------------------
83df96d6 53
3cd0b8c5 54const double RAD2DEG = 180.0 / M_PI;
83df96d6
JS
55
56// ----------------------------------------------------------------------------
3cd0b8c5 57// private functions
83df96d6
JS
58// ----------------------------------------------------------------------------
59
3cd0b8c5
RR
60static inline double dmax(double a, double b) { return a > b ? a : b; }
61static inline double dmin(double a, double b) { return a < b ? a : b; }
83df96d6 62
3cd0b8c5
RR
63static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
64
65//-----------------------------------------------------------------------------
66// Implement Pool of Graphic contexts. Creating them takes too much time.
67//-----------------------------------------------------------------------------
68
69#define GC_POOL_SIZE 200
70
71enum wxPoolGCType
72{
73 wxGC_ERROR = 0,
74 wxTEXT_MONO,
75 wxBG_MONO,
76 wxPEN_MONO,
77 wxBRUSH_MONO,
78 wxTEXT_COLOUR,
79 wxBG_COLOUR,
80 wxPEN_COLOUR,
81 wxBRUSH_COLOUR,
82 wxTEXT_SCREEN,
83 wxBG_SCREEN,
84 wxPEN_SCREEN,
85 wxBRUSH_SCREEN
86};
87
88struct wxGC
89{
90 GC m_gc;
91 wxPoolGCType m_type;
92 bool m_used;
93};
94
95static wxGC wxGCPool[GC_POOL_SIZE];
96
97static void wxInitGCPool()
98{
99 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) );
100}
83df96d6 101
3cd0b8c5 102static void wxCleanUpGCPool()
83df96d6 103{
3cd0b8c5
RR
104 for (int i = 0; i < GC_POOL_SIZE; i++)
105 {
106 if (wxGCPool[i].m_gc)
107 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc );
108 }
83df96d6
JS
109}
110
3cd0b8c5 111static GC wxGetPoolGC( Window window, wxPoolGCType type )
83df96d6 112{
3cd0b8c5
RR
113 for (int i = 0; i < GC_POOL_SIZE; i++)
114 {
115 if (!wxGCPool[i].m_gc)
116 {
117 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL );
118 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE );
119 wxGCPool[i].m_type = type;
120 wxGCPool[i].m_used = FALSE;
121 }
122 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
123 {
124 wxGCPool[i].m_used = TRUE;
125 return wxGCPool[i].m_gc;
126 }
127 }
128
129 wxFAIL_MSG( wxT("No GC available") );
130
131 return (GC) NULL;
83df96d6
JS
132}
133
3cd0b8c5
RR
134static void wxFreePoolGC( GC gc )
135{
136 for (int i = 0; i < GC_POOL_SIZE; i++)
137 {
138 if (wxGCPool[i].m_gc == gc)
139 {
140 wxGCPool[i].m_used = FALSE;
141 return;
142 }
143 }
144
145 wxFAIL_MSG( wxT("Wrong GC") );
146}
83df96d6
JS
147
148// ----------------------------------------------------------------------------
149// wxWindowDC
150// ----------------------------------------------------------------------------
151
3cd0b8c5
RR
152IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
153
83df96d6
JS
154wxWindowDC::wxWindowDC()
155{
3cd0b8c5
RR
156 m_display = (WXDisplay *) NULL;
157 m_penGC = (WXGC *) NULL;
158 m_brushGC = (WXGC *) NULL;
159 m_textGC = (WXGC *) NULL;
160 m_bgGC = (WXGC *) NULL;
161 m_cmap = (WXColormap *) NULL;
162 m_isMemDC = FALSE;
163 m_isScreenDC = FALSE;
164 m_owner = (wxWindow *)NULL;
83df96d6
JS
165}
166
167wxWindowDC::wxWindowDC( wxWindow *window )
168{
3cd0b8c5
RR
169 wxASSERT_MSG( window, wxT("DC needs a window") );
170
171 m_display = (WXDisplay *) NULL;
172 m_penGC = (WXGC *) NULL;
173 m_brushGC = (WXGC *) NULL;
174 m_textGC = (WXGC *) NULL;
175 m_bgGC = (WXGC *) NULL;
176 m_cmap = (WXColormap *) NULL;
177 m_owner = (wxWindow *)NULL;
178 m_isMemDC = FALSE;
179 m_isScreenDC = FALSE;
83df96d6 180 m_font = window->GetFont();
83df96d6 181
3cd0b8c5 182 m_window = (WXWindow*) window->GetMainWindow();
83df96d6 183
3cd0b8c5
RR
184 // not realized ?
185 if (!m_window)
186 {
187 // don't report problems
188 m_ok = TRUE;
189
190 return;
191 }
83df96d6 192
3cd0b8c5
RR
193 m_display = (WXDisplay *) wxGlobalDisplay();
194
195 int screen = DefaultScreen( (Display*) m_display );
196 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
83df96d6 197
3cd0b8c5 198 SetUpDC();
83df96d6 199
3cd0b8c5
RR
200 /* this must be done after SetUpDC, bacause SetUpDC calls the
201 repective SetBrush, SetPen, SetBackground etc functions
202 to set up the DC. SetBackground call m_owner->SetBackground
203 and this might not be desired as the standard dc background
204 is white whereas a window might assume gray to be the
205 standard (as e.g. wxStatusBar) */
83df96d6 206
3cd0b8c5 207 m_owner = window;
83df96d6
JS
208}
209
210wxWindowDC::~wxWindowDC()
211{
3cd0b8c5
RR
212 Destroy();
213}
214
215void wxWindowDC::SetUpDC()
216{
217 m_ok = TRUE;
218
219 wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
220
221 if (m_isScreenDC)
222 {
223 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_SCREEN );
224 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_SCREEN );
225 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN );
226 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN );
227 }
3cd0b8c5
RR
228 else
229 if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1))
230 {
231 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_MONO );
232 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_MONO );
233 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO );
234 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO );
235 }
3cd0b8c5 236 else
83df96d6 237 {
3cd0b8c5
RR
238 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR );
239 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_COLOUR );
240 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_COLOUR );
241 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_COLOUR );
83df96d6
JS
242 }
243
3cd0b8c5
RR
244 /* background colour */
245 m_backgroundBrush = *wxWHITE_BRUSH;
246 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
247 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel();
248
249 /* m_textGC */
250 m_textForegroundColour.CalcPixel( m_cmap );
251 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
252
253 m_textBackgroundColour.CalcPixel( m_cmap );
254 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
255
256 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid );
257
258 /* m_penGC */
259 m_pen.GetColour().CalcPixel( m_cmap );
260 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
261 XSetBackground( (Display*) m_display, (GC) m_penGC, bg_col );
262
263 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, 0, LineSolid, CapNotLast, JoinRound );
264
265 /* m_brushGC */
266 m_brush.GetColour().CalcPixel( m_cmap );
267 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
268 XSetBackground( (Display*) m_display, (GC) m_brushGC, bg_col );
269
270 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
271
272 /* m_bgGC */
273 XSetForeground( (Display*) m_display, (GC) m_bgGC, bg_col );
274 XSetBackground( (Display*) m_display, (GC) m_bgGC, bg_col );
275
276 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
277
278 /* ROPs */
279 XSetFunction( (Display*) m_display, (GC) m_textGC, GXcopy );
280 XSetFunction( (Display*) m_display, (GC) m_brushGC, GXcopy );
281 XSetFunction( (Display*) m_display, (GC)m_penGC, GXcopy );
282
283 /* clipping */
284 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
285 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
286 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
287 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
83df96d6 288
3cd0b8c5
RR
289 if (!hatch_bitmap)
290 {
1180fb81
RR
291 int xscreen = DefaultScreen( (Display*) m_display );
292 Window xroot = RootWindow( (Display*) m_display, xscreen );
293
3cd0b8c5 294 hatch_bitmap = hatches;
1180fb81
RR
295 hatch_bitmap[0] = XCreateBitmapFromData( (Display*) m_display, xroot, bdiag_bits, bdiag_width, bdiag_height );
296 hatch_bitmap[1] = XCreateBitmapFromData( (Display*) m_display, xroot, cdiag_bits, cdiag_width, cdiag_height );
297 hatch_bitmap[2] = XCreateBitmapFromData( (Display*) m_display, xroot, fdiag_bits, fdiag_width, fdiag_height );
298 hatch_bitmap[3] = XCreateBitmapFromData( (Display*) m_display, xroot, cross_bits, cross_width, cross_height );
299 hatch_bitmap[4] = XCreateBitmapFromData( (Display*) m_display, xroot, horiz_bits, horiz_width, horiz_height );
300 hatch_bitmap[5] = XCreateBitmapFromData( (Display*) m_display, xroot, verti_bits, verti_width, verti_height );
3cd0b8c5
RR
301 }
302}
83df96d6 303
3cd0b8c5
RR
304void wxWindowDC::DoGetSize( int* width, int* height ) const
305{
306 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
83df96d6 307
3cd0b8c5 308 m_owner->GetSize(width, height);
83df96d6
JS
309}
310
311void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
312 const wxColour& WXUNUSED(col), int WXUNUSED(style) )
313{
314 wxFAIL_MSG("not implemented");
315}
316
317bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
318{
319 // Generic (and therefore rather inefficient) method.
320 // Could be improved.
321 wxMemoryDC memdc;
322 wxBitmap bitmap(1, 1);
323 memdc.SelectObject(bitmap);
324 memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
325 memdc.SelectObject(wxNullBitmap);
326 wxImage image(bitmap);
327 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
328 return TRUE;
329}
330
331void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
332{
3cd0b8c5 333 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 334
3cd0b8c5
RR
335 if (m_pen.GetStyle() != wxTRANSPARENT)
336 {
337 if (m_window)
338 XDrawLine( (Display*) m_display, (Window) m_window,
339 (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
83df96d6 340
3cd0b8c5
RR
341 CalcBoundingBox(x1, y1);
342 CalcBoundingBox(x2, y2);
343 }
83df96d6
JS
344}
345
346void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
347{
3cd0b8c5 348 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 349
3cd0b8c5
RR
350 if (m_pen.GetStyle() != wxTRANSPARENT)
351 {
352 int w = 0;
353 int h = 0;
354 GetSize( &w, &h );
355 wxCoord xx = XLOG2DEV(x);
356 wxCoord yy = YLOG2DEV(y);
357 if (m_window)
358 {
359 XDrawLine( (Display*) m_display, (Window) m_window,
360 (GC) m_penGC, 0, yy, XLOG2DEVREL(w), yy );
361 XDrawLine( (Display*) m_display, (Window) m_window,
362 (GC) m_penGC, xx, 0, xx, YLOG2DEVREL(h) );
363 }
364 }
83df96d6
JS
365}
366
367void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
368{
3cd0b8c5
RR
369 wxCHECK_RET( Ok(), wxT("invalid window dc") );
370
371 wxCoord xx1 = XLOG2DEV(x1);
372 wxCoord yy1 = YLOG2DEV(y1);
373 wxCoord xx2 = XLOG2DEV(x2);
374 wxCoord yy2 = YLOG2DEV(y2);
375 wxCoord xxc = XLOG2DEV(xc);
376 wxCoord yyc = YLOG2DEV(yc);
377 double dx = xx1 - xxc;
378 double dy = yy1 - yyc;
379 double radius = sqrt((double)(dx*dx+dy*dy));
380 wxCoord r = (wxCoord)radius;
83df96d6
JS
381 double radius1, radius2;
382
383 if (xx1 == xx2 && yy1 == yy2)
384 {
385 radius1 = 0.0;
386 radius2 = 360.0;
387 }
83df96d6 388 else
3cd0b8c5 389 if (radius == 0.0)
83df96d6 390 {
3cd0b8c5 391 radius1 = radius2 = 0.0;
83df96d6 392 }
3cd0b8c5 393 else
83df96d6 394 {
3cd0b8c5
RR
395 radius1 = (xx1 - xxc == 0) ?
396 (yy1 - yyc < 0) ? 90.0 : -90.0 :
397 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
398 radius2 = (xx2 - xxc == 0) ?
399 (yy2 - yyc < 0) ? 90.0 : -90.0 :
400 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
83df96d6 401 }
3cd0b8c5
RR
402 wxCoord alpha1 = wxCoord(radius1 * 64.0);
403 wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0);
404 while (alpha2 <= 0) alpha2 += 360*64;
405 while (alpha1 > 360*64) alpha1 -= 360*64;
83df96d6 406
3cd0b8c5 407 if (m_window)
83df96d6 408 {
3cd0b8c5
RR
409 if (m_brush.GetStyle() != wxTRANSPARENT)
410 {
411 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
412 {
413 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
414 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
415 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
416
417 XFillArc( (Display*) m_display, (Window) m_window,
418 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
419
420 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
421 } else
422 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
423 {
424 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
425 m_deviceOriginX % 15, m_deviceOriginY % 15 );
426
427 XFillArc( (Display*) m_display, (Window) m_window,
428 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
429
430 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
431 } else
432 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
433 {
434 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
435 m_deviceOriginX % 16, m_deviceOriginY % 16 );
436
437 XFillArc( (Display*) m_display, (Window) m_window,
438 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
439
440 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
441 } else
442 if (m_brush.GetStyle() == wxSTIPPLE)
443 {
444 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
445 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
446 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
447
448 XFillArc( (Display*) m_display, (Window) m_window,
449 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
450
451 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
452 }
453 else
454 {
455 XFillArc( (Display*) m_display, (Window) m_window,
456 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
457 }
458 }
459
460 if (m_pen.GetStyle() != wxTRANSPARENT)
461 {
462 XDrawArc( (Display*) m_display, (Window) m_window,
463 (GC) m_penGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
464
465 XDrawLine( (Display*) m_display, (Window) m_window,
466 (GC) m_penGC, xx1, yy1, xxc, yyc );
467
468 XDrawLine( (Display*) m_display, (Window) m_window,
469 (GC) m_penGC, xxc, yyc, xx2, yy2 );
470 }
83df96d6 471 }
3cd0b8c5 472
83df96d6
JS
473 CalcBoundingBox (x1, y1);
474 CalcBoundingBox (x2, y2);
475}
476
477void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
478{
3cd0b8c5 479 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 480
3cd0b8c5
RR
481 wxCoord xx = XLOG2DEV(x);
482 wxCoord yy = YLOG2DEV(y);
483 wxCoord ww = m_signX * XLOG2DEVREL(width);
484 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 485
3cd0b8c5
RR
486 // CMB: handle -ve width and/or height
487 if (ww < 0) { ww = -ww; xx = xx - ww; }
488 if (hh < 0) { hh = -hh; yy = yy - hh; }
83df96d6 489
3cd0b8c5 490 if (m_window)
83df96d6 491 {
3cd0b8c5
RR
492 wxCoord start = wxCoord(sa * 64.0);
493 wxCoord end = wxCoord((ea-sa) * 64.0);
83df96d6 494
3cd0b8c5
RR
495 if (m_brush.GetStyle() != wxTRANSPARENT)
496 {
497 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
498 {
499 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
500 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
501 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
502
503 XFillArc( (Display*) m_display, (Window) m_window,
504 (GC) m_textGC, xx, yy, ww, hh, start, end );
505
506 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
507 } else
508 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
509 {
510 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
511 m_deviceOriginX % 15, m_deviceOriginY % 15 );
512
513 XFillArc( (Display*) m_display, (Window) m_window,
514 (GC) m_brushGC, xx, yy, ww, hh, start, end );
515
516 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
517 } else
518 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
519 {
520 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
521 m_deviceOriginX % 16, m_deviceOriginY % 16 );
522
523 XFillArc( (Display*) m_display, (Window) m_window,
524 (GC) m_brushGC, xx, yy, ww, hh, start, end );
525
526 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
527 } else
528 if (m_brush.GetStyle() == wxSTIPPLE)
529 {
530 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
531 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
532 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
533
534 XFillArc( (Display*) m_display, (Window) m_window,
535 (GC) m_brushGC, xx, yy, ww, hh, start, end );
536
537 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
538 }
539 else
540 {
541 XFillArc( (Display*) m_display, (Window) m_window,
542 (GC) m_brushGC, xx, yy, ww, hh, start, end );
543 }
544 }
83df96d6 545
3cd0b8c5
RR
546 if (m_pen.GetStyle() != wxTRANSPARENT)
547 {
548 XDrawArc( (Display*) m_display, (Window) m_window,
549 (GC) m_penGC, xx, yy, ww, hh, start, end );
550 }
83df96d6 551 }
3cd0b8c5 552
83df96d6
JS
553 CalcBoundingBox (x, y);
554 CalcBoundingBox (x + width, y + height);
555}
556
557void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
558{
3cd0b8c5 559 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 560
3cd0b8c5
RR
561 if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window)
562 XDrawPoint( (Display*) m_display, (Window) m_window,
563 (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
83df96d6 564
83df96d6
JS
565 CalcBoundingBox (x, y);
566}
567
568void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
569{
3cd0b8c5 570 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 571
3cd0b8c5
RR
572 if (m_pen.GetStyle() == wxTRANSPARENT) return;
573 if (n <= 0) return;
83df96d6 574
3cd0b8c5
RR
575 XPoint *xpoints = new XPoint[n];
576 for (int i = 0; i < n; i++)
83df96d6 577 {
3cd0b8c5
RR
578 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
579 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
580
581 CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset );
83df96d6 582 }
3cd0b8c5
RR
583 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n, 0 );
584
585 delete[] xpoints;
83df96d6
JS
586}
587
588void wxWindowDC::DoDrawPolygon( int n, wxPoint points[],
589 wxCoord xoffset, wxCoord yoffset, int fillStyle )
590{
3cd0b8c5 591 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 592
3cd0b8c5 593 if (n <= 0) return;
83df96d6 594
3cd0b8c5 595 XPoint *xpoints = new XPoint[n + 1];
83df96d6
JS
596 int i;
597 for (i = 0; i < n; i++)
598 {
3cd0b8c5
RR
599 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
600 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
601
83df96d6
JS
602 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
603 }
604
3cd0b8c5 605 if (m_window)
83df96d6 606 {
3cd0b8c5
RR
607 if (m_brush.GetStyle() != wxTRANSPARENT)
608 {
609
610 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
611 {
612 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
613 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
614 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
615
616 XFillPolygon( (Display*) m_display, (Window) m_window,
617 (GC) m_textGC, xpoints, n, Complex, 0);
618
619 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
620 } else
621 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
622 {
623 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
624 m_deviceOriginX % 15, m_deviceOriginY % 15 );
625
626 XFillPolygon( (Display*) m_display, (Window) m_window,
627 (GC) m_brushGC, xpoints, n, Complex, 0);
628
629 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
630 } else
631 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
632 {
633 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
634 m_deviceOriginX % 16, m_deviceOriginY % 16 );
635
636 XFillPolygon( (Display*) m_display, (Window) m_window,
637 (GC) m_brushGC, xpoints, n, Complex, 0);
638
639 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
640 } else
641 if (m_brush.GetStyle() == wxSTIPPLE)
642 {
643 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
644 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
645 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
646
647 XFillPolygon( (Display*) m_display, (Window) m_window,
648 (GC) m_brushGC, xpoints, n, Complex, 0);
649
650 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
651 }
652 else
653 {
654 XFillPolygon( (Display*) m_display, (Window) m_window,
655 (GC) m_brushGC, xpoints, n, Complex, 0);
656 }
657 }
83df96d6 658
3cd0b8c5
RR
659 if (m_pen.GetStyle () != wxTRANSPARENT)
660 {
661 // Close figure for XDrawLines
662 xpoints[i].x = xpoints[0].x;
663 xpoints[i].y = xpoints[0].y;
664
665 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n + 1, 0);
666 }
83df96d6
JS
667 }
668
3cd0b8c5 669 delete[] xpoints;
83df96d6
JS
670}
671
672void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
673{
3cd0b8c5 674 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 675
3cd0b8c5
RR
676 wxCoord xx = XLOG2DEV(x);
677 wxCoord yy = YLOG2DEV(y);
678 wxCoord ww = m_signX * XLOG2DEVREL(width);
679 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 680
3cd0b8c5
RR
681 // CMB: draw nothing if transformed w or h is 0
682 if (ww == 0 || hh == 0) return;
83df96d6 683
3cd0b8c5
RR
684 // CMB: handle -ve width and/or height
685 if (ww < 0) { ww = -ww; xx = xx - ww; }
686 if (hh < 0) { hh = -hh; yy = yy - hh; }
687
688 if (m_window)
83df96d6 689 {
3cd0b8c5
RR
690 if (m_brush.GetStyle() != wxTRANSPARENT)
691 {
692 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
693 {
694 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
695 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
696 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
697
698 XFillRectangle( (Display*) m_display, (Window) m_window,
699 (GC) m_textGC, xx, yy, ww, hh );
700
701 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
702 } else
703 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
704 {
705 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
706 m_deviceOriginX % 15, m_deviceOriginY % 15 );
707
708 XFillRectangle( (Display*) m_display, (Window) m_window,
709 (GC) m_brushGC, xx, yy, ww, hh );
710
711 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
712 } else
713 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
714 {
715 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
716 m_deviceOriginX % 16, m_deviceOriginY % 16 );
717
718 XFillRectangle( (Display*) m_display, (Window) m_window,
719 (GC) m_brushGC, xx, yy, ww, hh );
720
721 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
722 } else
723 if (m_brush.GetStyle() == wxSTIPPLE)
724 {
725 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
726 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
727 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
728
729 XFillRectangle( (Display*) m_display, (Window) m_window,
730 (GC) m_brushGC, xx, yy, ww, hh );
731
732 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
733 }
734 else
735 {
736 XFillRectangle( (Display*) m_display, (Window) m_window,
737 (GC) m_brushGC, xx, yy, ww, hh );
738 }
739 }
83df96d6 740
3cd0b8c5
RR
741 if (m_pen.GetStyle () != wxTRANSPARENT)
742 {
743 XDrawRectangle( (Display*) m_display, (Window) m_window,
887dd52f 744 (GC) m_penGC, xx, yy, ww-1, hh-1 );
3cd0b8c5 745 }
83df96d6 746 }
3cd0b8c5
RR
747
748 CalcBoundingBox( x, y );
749 CalcBoundingBox( x + width, y + height );
83df96d6
JS
750}
751
752void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
753{
3cd0b8c5
RR
754 // later
755}
83df96d6 756
3cd0b8c5
RR
757void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
758{
759 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 760
3cd0b8c5
RR
761 wxCoord xx = XLOG2DEV(x);
762 wxCoord yy = YLOG2DEV(y);
763 wxCoord ww = m_signX * XLOG2DEVREL(width);
764 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 765
3cd0b8c5
RR
766 // CMB: handle -ve width and/or height
767 if (ww < 0) { ww = -ww; xx = xx - ww; }
768 if (hh < 0) { hh = -hh; yy = yy - hh; }
83df96d6 769
3cd0b8c5 770 if (m_window)
83df96d6 771 {
3cd0b8c5
RR
772 if (m_brush.GetStyle() != wxTRANSPARENT)
773 {
774 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
775 {
776 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
777 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
778 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
779
780 XFillArc( (Display*) m_display, (Window) m_window,
781 (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 );
782
783 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
784 } else
785 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
786 {
787 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
788 m_deviceOriginX % 15, m_deviceOriginY % 15 );
789
790 XFillArc( (Display*) m_display, (Window) m_window,
791 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
792
793 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
794 } else
795 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
796 {
797 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
798 m_deviceOriginX % 16, m_deviceOriginY % 16 );
799
800 XFillArc( (Display*) m_display, (Window) m_window,
801 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
802
803 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
804 } else
805 if (m_brush.GetStyle() == wxSTIPPLE)
806 {
807 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
808 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
809 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
810
811 XFillArc( (Display*) m_display, (Window) m_window,
812 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
813
814 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
815 }
816 else
817 {
818 XFillArc( (Display*) m_display, (Window) m_window,
819 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
820 }
821 }
83df96d6 822
3cd0b8c5
RR
823 if (m_pen.GetStyle () != wxTRANSPARENT)
824 {
825 XDrawArc( (Display*) m_display, (Window) m_window,
826 (GC) m_penGC, xx, yy, ww, hh, 0, 360*64 );
827 }
83df96d6 828 }
83df96d6 829
3cd0b8c5
RR
830 CalcBoundingBox( x, y );
831 CalcBoundingBox( x + width, y + height );
832}
83df96d6 833
3cd0b8c5
RR
834void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
835{
83df96d6
JS
836}
837
3cd0b8c5
RR
838void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
839 wxCoord x, wxCoord y,
840 bool useMask )
83df96d6 841{
3cd0b8c5 842 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 843
3cd0b8c5
RR
844 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
845
3cd0b8c5 846 bool is_mono = (bitmap.GetBitmap() != NULL);
83df96d6 847
3cd0b8c5
RR
848 /* scale/translate size and position */
849 int xx = XLOG2DEV(x);
850 int yy = YLOG2DEV(y);
83df96d6 851
3cd0b8c5
RR
852 int w = bitmap.GetWidth();
853 int h = bitmap.GetHeight();
83df96d6 854
3cd0b8c5
RR
855 CalcBoundingBox( x, y );
856 CalcBoundingBox( x + w, y + h );
83df96d6 857
3cd0b8c5 858 if (!m_window) return;
83df96d6 859
3cd0b8c5
RR
860 int ww = XLOG2DEVREL(w);
861 int hh = YLOG2DEVREL(h);
83df96d6 862
3cd0b8c5
RR
863 /* compare to current clipping region */
864 if (!m_currentClippingRegion.IsNull())
83df96d6 865 {
3cd0b8c5
RR
866 wxRegion tmp( xx,yy,ww,hh );
867 tmp.Intersect( m_currentClippingRegion );
868 if (tmp.IsEmpty())
869 return;
83df96d6
JS
870 }
871
3cd0b8c5
RR
872 /* scale bitmap if required */
873 wxBitmap use_bitmap;
874 if ((w != ww) || (h != hh))
83df96d6 875 {
3cd0b8c5
RR
876 wxImage image( bitmap );
877 image.Rescale( ww, hh );
a11672a4 878#if 0
3cd0b8c5
RR
879 if (is_mono)
880 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
881 else
a11672a4 882#endif
3cd0b8c5
RR
883 use_bitmap = image.ConvertToBitmap();
884 }
885 else
886 {
887 use_bitmap = bitmap;
83df96d6 888 }
83df96d6 889
3cd0b8c5 890 /* apply mask if any */
a11672a4 891 WXPixmap mask = NULL;
3cd0b8c5 892 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
a11672a4 893 {
3cd0b8c5
RR
894 if (useMask && mask)
895 {
a11672a4
RR
896 WXPixmap new_mask = NULL;
897#if 0
3cd0b8c5
RR
898 if (!m_currentClippingRegion.IsNull())
899 {
900 GdkColor col;
901 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
902 GdkGC *gc = gdk_gc_new( new_mask );
903 col.pixel = 0;
904 gdk_gc_set_foreground( gc, &col );
905 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
906 col.pixel = 0;
907 gdk_gc_set_background( gc, &col );
908 col.pixel = 1;
909 gdk_gc_set_foreground( gc, &col );
910 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
911 gdk_gc_set_clip_origin( gc, -xx, -yy );
912 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
913 gdk_gc_set_stipple( gc, mask );
914 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
915 gdk_gc_unref( gc );
916 }
a11672a4 917#endif
3cd0b8c5
RR
918 if (is_mono)
919 {
920 if (new_mask)
a11672a4 921 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 922 else
a11672a4
RR
923 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
924 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
3cd0b8c5
RR
925 }
926 else
927 {
928 if (new_mask)
a11672a4 929 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 930 else
a11672a4
RR
931 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
932 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
3cd0b8c5 933 }
a11672a4 934
3cd0b8c5 935 if (new_mask)
a11672a4 936 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 937 }
a11672a4 938 }
83df96d6 939
3cd0b8c5
RR
940 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
941 drawing a mono-bitmap (XBitmap) we use the current text GC */
942 if (is_mono)
a11672a4
RR
943 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
944 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
3cd0b8c5 945 else
a11672a4
RR
946 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
947 (GC) m_penGC, 0, 0, w, h, xx, yy );
3cd0b8c5
RR
948
949 /* remove mask again if any */
950 if (useMask && mask)
83df96d6 951 {
3cd0b8c5 952 if (is_mono)
83df96d6 953 {
a11672a4
RR
954 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
955 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 956 if (!m_currentClippingRegion.IsNull())
a11672a4 957 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
958 }
959 else
960 {
a11672a4
RR
961 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
962 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 963 if (!m_currentClippingRegion.IsNull())
a11672a4 964 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6 965 }
83df96d6 966 }
83df96d6 967}
83df96d6 968
83df96d6
JS
969bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
970 wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
971 wxCoord xsrcMask, wxCoord ysrcMask )
972{
3cd0b8c5
RR
973 /* this is the nth try to get this utterly useless function to
974 work. it now completely ignores the scaling or translation
975 of the source dc, but scales correctly on the target dc and
976 knows about possible mask information in a memory dc. */
83df96d6 977
3cd0b8c5 978 wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
83df96d6 979
3cd0b8c5 980 wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
83df96d6 981
3cd0b8c5 982 if (!m_window) return FALSE;
83df96d6 983
3cd0b8c5
RR
984 // transform the source DC coords to the device ones
985 xsrc = source->XLOG2DEV(xsrc);
986 ysrc = source->YLOG2DEV(ysrc);
83df96d6 987
3cd0b8c5
RR
988 wxClientDC *srcDC = (wxClientDC*)source;
989 wxMemoryDC *memDC = (wxMemoryDC*)source;
83df96d6 990
3cd0b8c5
RR
991 bool use_bitmap_method = FALSE;
992 bool is_mono = FALSE;
83df96d6
JS
993
994 /* TODO: use the mask origin when drawing transparently */
995 if (xsrcMask == -1 && ysrcMask == -1)
996 {
997 xsrcMask = xsrc; ysrcMask = ysrc;
998 }
a11672a4 999
3cd0b8c5
RR
1000#if 0
1001 if (srcDC->m_isMemDC)
83df96d6 1002 {
3cd0b8c5 1003 if (!memDC->m_selected.Ok()) return FALSE;
83df96d6 1004
3cd0b8c5
RR
1005 /* we use the "XCopyArea" way to copy a memory dc into
1006 y different window if the memory dc BOTH
1007 a) doesn't have any mask or its mask isn't used
1008 b) it is clipped
1009 c) is not 1-bit */
83df96d6 1010
3cd0b8c5 1011 if (useMask && (memDC->m_selected.GetMask()))
83df96d6 1012 {
3cd0b8c5
RR
1013 /* we HAVE TO use the direct way for memory dcs
1014 that have mask since the XCopyArea doesn't know
1015 about masks */
1016 use_bitmap_method = TRUE;
1017 }
1018 else if (memDC->m_selected.GetDepth() == 1)
1019 {
1020 /* we HAVE TO use the direct way for memory dcs
1021 that are bitmaps because XCopyArea doesn't cope
1022 with different bit depths */
1023 is_mono = TRUE;
1024 use_bitmap_method = TRUE;
1025 }
1026 else if ((xsrc == 0) && (ysrc == 0) &&
1027 (width == memDC->m_selected.GetWidth()) &&
1028 (height == memDC->m_selected.GetHeight()))
1029 {
1030 /* we SHOULD use the direct way if all of the bitmap
1031 in the memory dc is copied in which case XCopyArea
1032 wouldn't be able able to boost performace by reducing
1033 the area to be scaled */
1034 use_bitmap_method = TRUE;
83df96d6
JS
1035 }
1036 else
1037 {
3cd0b8c5 1038 use_bitmap_method = FALSE;
83df96d6
JS
1039 }
1040 }
83df96d6 1041
3cd0b8c5
RR
1042 CalcBoundingBox( xdest, ydest );
1043 CalcBoundingBox( xdest + width, ydest + height );
1044
1045 /* scale/translate size and position */
1046 wxCoord xx = XLOG2DEV(xdest);
1047 wxCoord yy = YLOG2DEV(ydest);
1048
1049 wxCoord ww = XLOG2DEVREL(width);
1050 wxCoord hh = YLOG2DEVREL(height);
1051
1052 /* compare to current clipping region */
1053 if (!m_currentClippingRegion.IsNull())
83df96d6 1054 {
3cd0b8c5
RR
1055 wxRegion tmp( xx,yy,ww,hh );
1056 tmp.Intersect( m_currentClippingRegion );
1057 if (tmp.IsEmpty())
1058 return TRUE;
1059 }
83df96d6 1060
3cd0b8c5
RR
1061 int old_logical_func = m_logicalFunction;
1062 SetLogicalFunction( logical_func );
83df96d6 1063
3cd0b8c5
RR
1064 if (use_bitmap_method)
1065 {
1066 /* scale/translate bitmap size */
1067 wxCoord bm_width = memDC->m_selected.GetWidth();
1068 wxCoord bm_height = memDC->m_selected.GetHeight();
83df96d6 1069
3cd0b8c5
RR
1070 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1071 wxCoord bm_hh = YLOG2DEVREL( bm_height );
83df96d6 1072
3cd0b8c5
RR
1073 /* scale bitmap if required */
1074 wxBitmap use_bitmap;
83df96d6 1075
3cd0b8c5
RR
1076 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1077 {
1078 wxImage image( memDC->m_selected );
1079 image = image.Scale( bm_ww, bm_hh );
83df96d6 1080
3cd0b8c5
RR
1081 if (is_mono)
1082 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1083 else
1084 use_bitmap = image.ConvertToBitmap();
1085 }
1086 else
1087 {
1088 use_bitmap = memDC->m_selected;
1089 }
1090
1091 /* apply mask if any */
1092 GdkBitmap *mask = (GdkBitmap *) NULL;
1093 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
83df96d6 1094
3cd0b8c5 1095 if (useMask && mask)
83df96d6 1096 {
3cd0b8c5
RR
1097 GdkBitmap *new_mask = (GdkBitmap*) NULL;
1098 if (!m_currentClippingRegion.IsNull())
83df96d6 1099 {
3cd0b8c5
RR
1100 GdkColor col;
1101 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1102 GdkGC *gc = gdk_gc_new( new_mask );
1103 col.pixel = 0;
1104 gdk_gc_set_foreground( gc, &col );
1105 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1106 col.pixel = 0;
1107 gdk_gc_set_background( gc, &col );
1108 col.pixel = 1;
1109 gdk_gc_set_foreground( gc, &col );
1110 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1111 gdk_gc_set_clip_origin( gc, -xx, -yy );
1112 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1113 gdk_gc_set_stipple( gc, mask );
1114 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1115 gdk_gc_unref( gc );
83df96d6
JS
1116 }
1117
3cd0b8c5 1118 if (is_mono)
83df96d6 1119 {
3cd0b8c5
RR
1120 if (new_mask)
1121 gdk_gc_set_clip_mask( m_textGC, new_mask );
1122 else
1123 gdk_gc_set_clip_mask( m_textGC, mask );
1124 gdk_gc_set_clip_origin( m_textGC, xx, yy );
83df96d6
JS
1125 }
1126 else
1127 {
3cd0b8c5
RR
1128 if (new_mask)
1129 gdk_gc_set_clip_mask( m_penGC, new_mask );
1130 else
1131 gdk_gc_set_clip_mask( m_penGC, mask );
1132 gdk_gc_set_clip_origin( m_penGC, xx, yy );
83df96d6 1133 }
3cd0b8c5
RR
1134 if (new_mask)
1135 gdk_bitmap_unref( new_mask );
1136 }
83df96d6 1137
3cd0b8c5
RR
1138 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1139 drawing a mono-bitmap (XBitmap) we use the current text GC */
83df96d6 1140
3cd0b8c5
RR
1141 if (is_mono)
1142 gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
83df96d6 1143 else
3cd0b8c5 1144 gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh );
83df96d6 1145
3cd0b8c5
RR
1146 /* remove mask again if any */
1147 if (useMask && mask)
83df96d6 1148 {
3cd0b8c5
RR
1149 if (is_mono)
1150 {
1151 gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL );
1152 gdk_gc_set_clip_origin( m_textGC, 0, 0 );
1153 if (!m_currentClippingRegion.IsNull())
1154 gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
1155 }
1156 else
83df96d6 1157 {
3cd0b8c5
RR
1158 gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
1159 gdk_gc_set_clip_origin( m_penGC, 0, 0 );
1160 if (!m_currentClippingRegion.IsNull())
1161 gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
83df96d6
JS
1162 }
1163 }
83df96d6 1164 }
3cd0b8c5 1165 else /* use_bitmap_method */
83df96d6 1166 {
3cd0b8c5 1167 if ((width != ww) || (height != hh))
83df96d6 1168 {
3cd0b8c5
RR
1169 /* draw source window into a bitmap as we cannot scale
1170 a window in contrast to a bitmap. this would actually
1171 work with memory dcs as well, but we'd lose the mask
1172 information and waste one step in this process since
1173 a memory already has a bitmap. all this is slightly
1174 inefficient as we could take an XImage directly from
1175 an X window, but we'd then also have to care that
1176 the window is not outside the screen (in which case
1177 we'd get a BadMatch or what not).
1178 Is a double XGetImage and combined XGetPixel and
1179 XPutPixel really faster? I'm not sure. look at wxXt
1180 for a different implementation of the same problem. */
1181
1182 wxBitmap bitmap( width, height );
1183
1184 /* copy including child window contents */
1185 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
1186 gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
1187 srcDC->GetWindow(),
1188 xsrc, ysrc, width, height );
1189 gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
1190
1191 /* scale image */
1192 wxImage image( bitmap );
1193 image = image.Scale( ww, hh );
1194
1195 /* convert to bitmap */
1196 bitmap = image.ConvertToBitmap();
1197
1198 /* draw scaled bitmap */
1199 gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
83df96d6 1200
83df96d6
JS
1201 }
1202 else
3cd0b8c5
RR
1203 {
1204 /* No scaling and not a memory dc with a mask either */
1205
1206 /* copy including child window contents */
1207 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
1208 gdk_window_copy_area( m_window, m_penGC, xx, yy,
1209 srcDC->GetWindow(),
1210 xsrc, ysrc, width, height );
1211 gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
1212 }
83df96d6
JS
1213 }
1214
3cd0b8c5
RR
1215 SetLogicalFunction( old_logical_func );
1216 return TRUE;
1217#endif
83df96d6 1218
3cd0b8c5 1219 return FALSE;
83df96d6
JS
1220}
1221
3cd0b8c5 1222void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
83df96d6 1223{
3cd0b8c5 1224 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1225
3cd0b8c5 1226 if (!m_window) return;
83df96d6 1227
3cd0b8c5 1228 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
83df96d6 1229
3cd0b8c5 1230 wxCHECK_RET( xfont, wxT("invalid font") );
83df96d6 1231
3cd0b8c5
RR
1232 x = XLOG2DEV(x);
1233 y = YLOG2DEV(y);
83df96d6 1234
3cd0b8c5
RR
1235#if 0
1236 wxCoord width = gdk_string_width( font, text.mbc_str() );
1237 wxCoord height = font->ascent + font->descent;
83df96d6 1238
3cd0b8c5 1239 if ( m_backgroundMode == wxSOLID )
83df96d6 1240 {
3cd0b8c5
RR
1241 gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
1242 gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
1243 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
83df96d6 1244 }
3cd0b8c5
RR
1245#endif
1246
1247 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
788519c6 1248#if !wxUSE_NANOX
3cd0b8c5 1249 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
788519c6
JS
1250#endif
1251 {
3cd0b8c5 1252 XDrawString( (Display*) m_display, (Window) m_window,
788519c6
JS
1253 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1254 }
83df96d6
JS
1255
1256#if 0
3cd0b8c5 1257 if (m_font.GetUnderlined())
83df96d6 1258 {
788519c6 1259 wxCoord ul_y = y + XFontStructGetAscent(font);
3cd0b8c5
RR
1260 if (font->descent > 0) ul_y++;
1261 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
83df96d6 1262 }
83df96d6 1263
3cd0b8c5
RR
1264 width = wxCoord(width / m_scaleX);
1265 height = wxCoord(height / m_scaleY);
1266
1267 CalcBoundingBox (x + width, y + height);
83df96d6 1268 CalcBoundingBox (x, y);
3cd0b8c5 1269#endif
83df96d6
JS
1270}
1271
3cd0b8c5 1272void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
83df96d6 1273{
3cd0b8c5 1274 // later
83df96d6
JS
1275}
1276
1277void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1278 wxCoord *descent, wxCoord *externalLeading,
1279 wxFont *font ) const
1280{
1281 wxCHECK_RET( Ok(), "invalid dc" );
1282
3cd0b8c5
RR
1283 wxFont fontToUse = m_font;
1284 if (font) fontToUse = *font;
83df96d6 1285
3cd0b8c5 1286 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
83df96d6 1287
3cd0b8c5 1288 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1289
3cd0b8c5
RR
1290 wxCHECK_RET( xfont, wxT("invalid font") );
1291
83df96d6
JS
1292 int direction, ascent, descent2;
1293 XCharStruct overall;
83df96d6 1294
788519c6 1295 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
83df96d6
JS
1296 &ascent, &descent2, &overall);
1297
3cd0b8c5
RR
1298 if (width)
1299 *width = (wxCoord)( overall.width / m_scaleX );
1300 if (height)
1301 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1302 if (descent)
3cd0b8c5 1303 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1304 if (externalLeading)
3cd0b8c5 1305 *externalLeading = 0; // ??
83df96d6
JS
1306}
1307
1308wxCoord wxWindowDC::GetCharWidth() const
1309{
1310 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1311
83df96d6
JS
1312 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1313
3cd0b8c5
RR
1314 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1315
1316 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1317
1318 int direction, ascent, descent;
1319 XCharStruct overall;
3cd0b8c5
RR
1320
1321 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1322
1323 return (wxCoord)(overall.width / m_scaleX);
83df96d6
JS
1324}
1325
1326wxCoord wxWindowDC::GetCharHeight() const
1327{
1328 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1329
83df96d6
JS
1330 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1331
3cd0b8c5
RR
1332 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1333
1334 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1335
1336 int direction, ascent, descent;
1337 XCharStruct overall;
3cd0b8c5
RR
1338
1339 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1340
1341 return (wxCoord)((ascent+descent) / m_scaleY);
83df96d6
JS
1342}
1343
1344void wxWindowDC::Clear()
1345{
3cd0b8c5 1346 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1347
3cd0b8c5 1348 if (!m_window) return;
83df96d6 1349
3cd0b8c5
RR
1350 /* - we either are a memory dc or have a window as the
1351 owner. anything else shouldn't happen.
1352 - we don't use gdk_window_clear() as we don't set
1353 the window's background colour anymore. it is too
1354 much pain to keep the DC's and the window's back-
1355 ground colour in synch. */
83df96d6 1356
3cd0b8c5
RR
1357 if (m_owner)
1358 {
1359 int width,height;
1360 m_owner->GetSize( &width, &height );
1361 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1362 return;
1363 }
83df96d6 1364
3cd0b8c5
RR
1365 if (m_isMemDC)
1366 {
1367 int width,height;
1368 GetSize( &width, &height );
1369 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1370 return;
1371 }
83df96d6
JS
1372}
1373
1374void wxWindowDC::SetFont( const wxFont &font )
1375{
1376 wxCHECK_RET( Ok(), "invalid dc" );
1377
1378 m_font = font;
83df96d6
JS
1379}
1380
1381void wxWindowDC::SetPen( const wxPen &pen )
1382{
3cd0b8c5
RR
1383 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1384
1385 if (m_pen == pen) return;
83df96d6
JS
1386
1387 m_pen = pen;
83df96d6 1388
3cd0b8c5 1389 if (!m_pen.Ok()) return;
83df96d6 1390
3cd0b8c5 1391 if (!m_window) return;
83df96d6 1392
3cd0b8c5
RR
1393 int width = m_pen.GetWidth();
1394 if (width <= 0)
1395 {
1396 // CMB: if width is non-zero scale it with the dc
1397 width = 1;
1398 }
1399 else
1400 {
1401 // X doesn't allow different width in x and y and so we take
1402 // the average
1403 double w = 0.5 +
1404 ( fabs((double) XLOG2DEVREL(width)) +
1405 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1406 width = (int)w;
1407 }
1408
1409 static const wxX11Dash dotted[] = {1, 1};
1410 static const wxX11Dash short_dashed[] = {2, 2};
1411 static const wxX11Dash long_dashed[] = {2, 4};
1412 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1413
1414 // We express dash pattern in pen width unit, so we are
1415 // independent of zoom factor and so on...
1416 int req_nb_dash;
1417 const wxX11Dash *req_dash;
1418
1419 int lineStyle = LineSolid;
1420 switch (m_pen.GetStyle())
83df96d6 1421 {
83df96d6 1422 case wxUSER_DASH:
3cd0b8c5
RR
1423 {
1424 lineStyle = LineOnOffDash;
1425 req_nb_dash = m_pen.GetDashCount();
1426 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1427 break;
3cd0b8c5 1428 }
83df96d6 1429 case wxDOT:
3cd0b8c5
RR
1430 {
1431 lineStyle = LineOnOffDash;
83df96d6
JS
1432 req_nb_dash = 2;
1433 req_dash = dotted;
83df96d6 1434 break;
3cd0b8c5 1435 }
83df96d6 1436 case wxLONG_DASH:
3cd0b8c5
RR
1437 {
1438 lineStyle = LineOnOffDash;
83df96d6
JS
1439 req_nb_dash = 2;
1440 req_dash = long_dashed;
83df96d6 1441 break;
3cd0b8c5
RR
1442 }
1443 case wxSHORT_DASH:
1444 {
1445 lineStyle = LineOnOffDash;
1446 req_nb_dash = 2;
1447 req_dash = short_dashed;
1448 break;
1449 }
83df96d6 1450 case wxDOT_DASH:
3cd0b8c5
RR
1451 {
1452// lineStyle = LineDoubleDash;
1453 lineStyle = LineOnOffDash;
83df96d6
JS
1454 req_nb_dash = 4;
1455 req_dash = dotted_dashed;
83df96d6 1456 break;
3cd0b8c5
RR
1457 }
1458
1459 case wxTRANSPARENT:
1460 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1461 case wxSTIPPLE:
1462 case wxSOLID:
83df96d6 1463 default:
3cd0b8c5
RR
1464 {
1465 lineStyle = LineSolid;
74dc5eb6 1466 req_dash = (wxX11Dash*)NULL;
83df96d6 1467 req_nb_dash = 0;
3cd0b8c5 1468 break;
83df96d6 1469 }
3cd0b8c5 1470 }
83df96d6 1471
3cd0b8c5
RR
1472 int capStyle = CapRound;
1473 switch (m_pen.GetCap())
1474 {
1475 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1476 case wxCAP_BUTT: { capStyle = CapButt; break; }
1477 case wxCAP_ROUND:
1478 default:
83df96d6 1479 {
3cd0b8c5 1480 if (width <= 1)
83df96d6 1481 {
3cd0b8c5
RR
1482 width = 0;
1483 capStyle = CapNotLast;
83df96d6
JS
1484 }
1485 else
1486 {
3cd0b8c5 1487 capStyle = CapRound;
83df96d6 1488 }
83df96d6
JS
1489 break;
1490 }
3cd0b8c5 1491 }
83df96d6 1492
3cd0b8c5
RR
1493 int joinStyle = JoinRound;
1494 switch (m_pen.GetJoin())
1495 {
1496 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1497 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1498 case wxJOIN_ROUND:
3cd0b8c5 1499 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1500 }
1501
3cd0b8c5 1502 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1503
3cd0b8c5
RR
1504 m_pen.GetColour().CalcPixel( m_cmap );
1505 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1506}
83df96d6 1507
3cd0b8c5
RR
1508void wxWindowDC::SetBrush( const wxBrush &brush )
1509{
1510 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1511
3cd0b8c5 1512 if (m_brush == brush) return;
83df96d6 1513
3cd0b8c5
RR
1514 m_brush = brush;
1515
1516 if (!m_brush.Ok()) return;
83df96d6 1517
3cd0b8c5
RR
1518 if (!m_window) return;
1519
1520 m_brush.GetColour().CalcPixel( m_cmap );
1521 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1522
1523 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1524
1525 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
83df96d6 1526 {
3cd0b8c5 1527 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1528 {
3cd0b8c5
RR
1529 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1530 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1531 }
1532 else
1533 {
3cd0b8c5 1534 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1535 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1536 }
3cd0b8c5 1537 }
83df96d6 1538
3cd0b8c5
RR
1539 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1540 {
1541 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1542 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1543 }
83df96d6 1544
3cd0b8c5
RR
1545 if (IS_HATCH(m_brush.GetStyle()))
1546 {
1547 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1548 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1549 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1550 }
83df96d6
JS
1551}
1552
3cd0b8c5 1553void wxWindowDC::SetBackground( const wxBrush &brush )
83df96d6 1554{
3cd0b8c5
RR
1555 /* CMB 21/7/98: Added SetBackground. Sets background brush
1556 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 1557
3cd0b8c5 1558 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1559
3cd0b8c5 1560 if (m_backgroundBrush == brush) return;
83df96d6 1561
3cd0b8c5 1562 m_backgroundBrush = brush;
83df96d6 1563
3cd0b8c5 1564 if (!m_backgroundBrush.Ok()) return;
83df96d6 1565
3cd0b8c5 1566 if (!m_window) return;
83df96d6 1567
3cd0b8c5
RR
1568 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1569 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1570 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1571 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1572 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 1573
3cd0b8c5 1574 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 1575
3cd0b8c5 1576 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
83df96d6 1577 {
3cd0b8c5 1578 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 1579 {
3cd0b8c5
RR
1580 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1581 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 1582 }
3cd0b8c5 1583 else
83df96d6 1584 {
3cd0b8c5 1585 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 1586 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 1587 }
83df96d6
JS
1588 }
1589
3cd0b8c5 1590 if (IS_HATCH(m_backgroundBrush.GetStyle()))
83df96d6 1591 {
3cd0b8c5
RR
1592 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1593 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1594 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 1595 }
83df96d6
JS
1596}
1597
1598void wxWindowDC::SetLogicalFunction( int function )
1599{
1600 wxCHECK_RET( Ok(), "invalid dc" );
1601
1602 int x_function;
1603
83df96d6
JS
1604 if (m_logicalFunction == function)
1605 return;
1606
3cd0b8c5
RR
1607 // VZ: shouldn't this be a CHECK?
1608 if (!m_window)
1609 return;
1610
83df96d6
JS
1611 switch (function)
1612 {
1613 case wxCLEAR:
1614 x_function = GXclear;
1615 break;
1616 case wxXOR:
1617 x_function = GXxor;
1618 break;
1619 case wxINVERT:
1620 x_function = GXinvert;
1621 break;
1622 case wxOR_REVERSE:
1623 x_function = GXorReverse;
1624 break;
1625 case wxAND_REVERSE:
1626 x_function = GXandReverse;
1627 break;
1628 case wxAND:
1629 x_function = GXand;
1630 break;
1631 case wxOR:
1632 x_function = GXor;
1633 break;
1634 case wxAND_INVERT:
1635 x_function = GXandInverted;
1636 break;
1637 case wxNO_OP:
1638 x_function = GXnoop;
1639 break;
1640 case wxNOR:
1641 x_function = GXnor;
1642 break;
1643 case wxEQUIV:
1644 x_function = GXequiv;
1645 break;
1646 case wxSRC_INVERT:
1647 x_function = GXcopyInverted;
1648 break;
1649 case wxOR_INVERT:
1650 x_function = GXorInverted;
1651 break;
1652 case wxNAND:
1653 x_function = GXnand;
1654 break;
1655 case wxSET:
1656 x_function = GXset;
1657 break;
1658 case wxCOPY:
1659 default:
1660 x_function = GXcopy;
1661 break;
1662 }
1663
3cd0b8c5
RR
1664 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
1665 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 1666
3cd0b8c5
RR
1667 // to stay compatible with wxMSW, we don't apply ROPs to the text
1668 // operations (i.e. DrawText/DrawRotatedText).
1669 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1670 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
1671
83df96d6 1672 m_logicalFunction = function;
83df96d6
JS
1673}
1674
1675void wxWindowDC::SetTextForeground( const wxColour &col )
1676{
3cd0b8c5 1677 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1678
3cd0b8c5
RR
1679 // don't set m_textForegroundColour to an invalid colour as we'd crash
1680 // later then (we use m_textForegroundColour.GetColor() without checking
1681 // in a few places)
1682 if ( !col.Ok() || (m_textForegroundColour == col) )
83df96d6
JS
1683 return;
1684
1685 m_textForegroundColour = col;
1686
3cd0b8c5
RR
1687 if (m_window)
1688 {
1689 m_textForegroundColour.CalcPixel( m_cmap );
1690 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
1691 }
83df96d6
JS
1692}
1693
1694void wxWindowDC::SetTextBackground( const wxColour &col )
1695{
3cd0b8c5 1696 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1697
3cd0b8c5
RR
1698 // same as above
1699 if ( !col.Ok() || (m_textBackgroundColour == col) )
83df96d6
JS
1700 return;
1701
1702 m_textBackgroundColour = col;
3cd0b8c5
RR
1703
1704 if (m_window)
1705 {
1706 m_textBackgroundColour.CalcPixel( m_cmap );
1707 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
1708 }
83df96d6
JS
1709}
1710
1711void wxWindowDC::SetBackgroundMode( int mode )
1712{
3cd0b8c5
RR
1713 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1714
83df96d6 1715 m_backgroundMode = mode;
3cd0b8c5
RR
1716
1717 if (!m_window) return;
1718
1719 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1720 // transparent/solid background mode
1721
1722 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1723 {
1724 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
1725 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
1726 }
83df96d6
JS
1727}
1728
1729void wxWindowDC::SetPalette( const wxPalette& palette )
1730{
3cd0b8c5 1731#if 0
83df96d6
JS
1732 if (m_window)
1733 {
1734 if (palette.Ok())
1735 /* Use GetXColormap */
1736 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1737 (Colormap) palette.GetXColormap());
1738 else
1739 /* Use wxGetMainColormap */
1740 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1741 (Colormap) wxTheApp->GetMainColormap(m_display));
1742 }
3cd0b8c5 1743#endif
83df96d6
JS
1744}
1745
3cd0b8c5 1746void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 1747{
3cd0b8c5 1748 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1749
3cd0b8c5 1750 if (!m_window) return;
83df96d6 1751
3cd0b8c5
RR
1752 wxRect rect;
1753 rect.x = XLOG2DEV(x);
1754 rect.y = YLOG2DEV(y);
1755 rect.width = XLOG2DEVREL(width);
1756 rect.height = YLOG2DEVREL(height);
1757
1758 if (!m_currentClippingRegion.IsNull())
1759 m_currentClippingRegion.Intersect( rect );
83df96d6 1760 else
3cd0b8c5
RR
1761 m_currentClippingRegion.Union( rect );
1762
1763#if USE_PAINT_REGION
1764 if (!m_paintClippingRegion.IsNull())
1765 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1766#endif
1767
1768 wxCoord xx, yy, ww, hh;
1769 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1770 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1771
1772 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1773 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1774 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1775 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1776}
83df96d6 1777
3cd0b8c5
RR
1778void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1779{
1780 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1781
3cd0b8c5 1782 if (region.Empty())
83df96d6 1783 {
3cd0b8c5
RR
1784 DestroyClippingRegion();
1785 return;
83df96d6 1786 }
3cd0b8c5
RR
1787
1788 if (!m_window) return;
1789
1790 if (!m_currentClippingRegion.IsNull())
1791 m_currentClippingRegion.Intersect( region );
83df96d6 1792 else
3cd0b8c5 1793 m_currentClippingRegion.Union( region );
83df96d6 1794
3cd0b8c5
RR
1795#if USE_PAINT_REGION
1796 if (!m_paintClippingRegion.IsNull())
1797 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1798#endif
83df96d6 1799
3cd0b8c5
RR
1800 wxCoord xx, yy, ww, hh;
1801 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1802 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1803
1804 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1805 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1806 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1807 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1808}
1809
3cd0b8c5 1810void wxWindowDC::DestroyClippingRegion()
83df96d6 1811{
3cd0b8c5 1812 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1813
3cd0b8c5 1814 wxDC::DestroyClippingRegion();
83df96d6 1815
3cd0b8c5 1816 m_currentClippingRegion.Clear();
83df96d6 1817
3cd0b8c5
RR
1818#if USE_PAINT_REGION
1819 if (!m_paintClippingRegion.IsEmpty())
1820 m_currentClippingRegion.Union( m_paintClippingRegion );
1821#endif
83df96d6 1822
3cd0b8c5 1823 if (!m_window) return;
83df96d6 1824
3cd0b8c5
RR
1825 if (m_currentClippingRegion.IsEmpty())
1826 {
1827 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1828 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
1829 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1830 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
1831 }
1832 else
1833 {
1834 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1835 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1836 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1837 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1838 }
1839}
83df96d6 1840
3cd0b8c5 1841void wxWindowDC::Destroy()
83df96d6 1842{
3cd0b8c5
RR
1843 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
1844 m_penGC = NULL;
1845 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
1846 m_brushGC = NULL;
1847 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
1848 m_textGC = NULL;
1849 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
1850 m_bgGC = NULL;
1851}
83df96d6 1852
3cd0b8c5
RR
1853void wxWindowDC::ComputeScaleAndOrigin()
1854{
1855 /* CMB: copy scale to see if it changes */
1856 double origScaleX = m_scaleX;
1857 double origScaleY = m_scaleY;
83df96d6 1858
3cd0b8c5 1859 wxDC::ComputeScaleAndOrigin();
83df96d6 1860
3cd0b8c5
RR
1861 /* CMB: if scale has changed call SetPen to recalulate the line width */
1862 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
1863 (m_pen.Ok()))
1864 {
1865 /* this is a bit artificial, but we need to force wxDC to think
1866 the pen has changed */
1867 wxPen pen = m_pen;
1868 m_pen = wxNullPen;
1869 SetPen( pen );
1870 }
83df96d6
JS
1871}
1872
83df96d6
JS
1873wxSize wxWindowDC::GetPPI() const
1874{
1875 return wxSize(100, 100);
1876}
1877
1878int wxWindowDC::GetDepth() const
1879{
3cd0b8c5 1880 wxFAIL_MSG(wxT("not implemented"));
83df96d6 1881
3cd0b8c5
RR
1882 return -1;
1883}
83df96d6
JS
1884
1885// ----------------------------------------------------------------------------
1886// wxPaintDC
1887// ----------------------------------------------------------------------------
1888
3cd0b8c5
RR
1889IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
1890
1934d291 1891wxPaintDC::wxPaintDC(wxWindow* win)
3cd0b8c5
RR
1892 : wxClientDC(win)
1893{
1894#if USE_PAINT_REGION
1895 if (!win->GetClipPaintRegion())
1896 return;
1897
1898 m_paintClippingRegion = win->GetUpdateRegion();
1899 Region region = (Region) m_paintClippingRegion.GetX11Region();
1900 if (region)
1901 {
1902 m_paintClippingRegion = win->GetUpdateRegion();
1903 Region region2 = (Region) m_paintClippingRegion.GetX11Region();
1904 if (region2)
1905 {
1906 m_currentClippingRegion.Union( m_paintClippingRegion );
1907
1908 XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
1909 XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
1910 XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
1911 XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
1912 }
1913 }
1914#endif // USE_PAINT_REGION
1915}
1916
1917//-----------------------------------------------------------------------------
1918// wxClientDC
1919//-----------------------------------------------------------------------------
1920
1921IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
1922
1923wxClientDC::wxClientDC( wxWindow *win )
1924 : wxWindowDC( win )
83df96d6 1925{
3cd0b8c5 1926 wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
a11672a4
RR
1927
1928#ifdef __WXUNIVERSAL__
1929 wxPoint ptOrigin = win->GetClientAreaOrigin();
1930 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
1931 wxSize size = win->GetClientSize();
1932 SetClippingRegion(wxPoint(0, 0), size);
1933#endif // __WXUNIVERSAL__
83df96d6
JS
1934}
1935
3cd0b8c5 1936void wxClientDC::DoGetSize(int *width, int *height) const
83df96d6 1937{
3cd0b8c5
RR
1938 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
1939
1940 m_owner->GetClientSize( width, height );
83df96d6
JS
1941}
1942
1943// ----------------------------------------------------------------------------
3cd0b8c5 1944// wxDCModule
83df96d6
JS
1945// ----------------------------------------------------------------------------
1946
3cd0b8c5 1947class wxDCModule : public wxModule
83df96d6 1948{
3cd0b8c5
RR
1949public:
1950 bool OnInit();
1951 void OnExit();
83df96d6 1952
3cd0b8c5
RR
1953private:
1954 DECLARE_DYNAMIC_CLASS(wxDCModule)
1955};
83df96d6 1956
3cd0b8c5 1957IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 1958
3cd0b8c5
RR
1959bool wxDCModule::OnInit()
1960{
1961 wxInitGCPool();
1962 return TRUE;
83df96d6
JS
1963}
1964
3cd0b8c5 1965void wxDCModule::OnExit()
83df96d6 1966{
3cd0b8c5 1967 wxCleanUpGCPool();
83df96d6 1968}