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