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