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