]> git.saurik.com Git - wxWidgets.git/blame - src/motif/dcclient.cpp
Better fix for modal/modeless wizards.
[wxWidgets.git] / src / motif / dcclient.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: dcclient.cpp
3// Purpose: wxClientDC class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
16c1f7f3 12/*
af0bb3b1
VZ
13 About pens, brushes, and the autoSetting flag:
14
729be74d
MB
15 Under X, pens and brushes control some of the same X drawing
16 parameters. Therefore, it is impossible to independently maintain
17 the current pen and the current brush. Also, some settings depend on
18 the current logical function. The m_currentFill, etc. instance
19 variables remember state across the brush and pen.
af0bb3b1
VZ
20
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
25
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
16c1f7f3
JS
29*/
30
af0bb3b1
VZ
31// ============================================================================
32// declarations
33// ============================================================================
34
35// ----------------------------------------------------------------------------
36// headers
37// ----------------------------------------------------------------------------
38
1248b41f
MB
39// For compilers that support precompilation, includes "wx.h".
40#include "wx/wxprec.h"
41
4bb6408c
JS
42#include "wx/dcclient.h"
43#include "wx/dcmemory.h"
dfc54541 44#include "wx/window.h"
16c1f7f3 45#include "wx/app.h"
a91b47e8 46#include "wx/image.h"
b1699cd3 47#include "wx/log.h"
463c4d71 48#include "wx/math.h"
4bb6408c 49
338dd992
JJ
50#ifdef __VMS__
51#pragma message disable nosimpint
52#endif
dfc54541 53#include <Xm/Xm.h>
338dd992
JJ
54#ifdef __VMS__
55#pragma message enable nosimpint
56#endif
dfc54541
JS
57
58#include "wx/motif/private.h"
59
280108ed
VZ
60#ifdef __EMX__
61 #include <float.h> // for M_PI
62#endif // __EMX__
63
16c1f7f3
JS
64#include "bdiag.xbm"
65#include "fdiag.xbm"
66#include "cdiag.xbm"
67#include "horiz.xbm"
68#include "verti.xbm"
69#include "cross.xbm"
70
71static Pixmap bdiag, cdiag, fdiag, cross, horiz, verti;
72
af0bb3b1 73// ----------------------------------------------------------------------------
4bb6408c 74// constants
af0bb3b1 75// ----------------------------------------------------------------------------
4bb6408c 76
af0bb3b1 77// Fudge factor (VZ: what??)
aaa38880 78#define WX_GC_CF 1
4bb6408c 79
af0bb3b1
VZ
80// ----------------------------------------------------------------------------
81// macros
82// ----------------------------------------------------------------------------
4bb6408c 83
ab9d0a8c
WS
84IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
85IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
86IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
87
88#ifndef IS_HATCH
89 // IS_HATCH exists for WXWIN_COMPATIBILITY_2_4 only
90 // but wxMotif needs it for its internals here
cb9d5bd0 91 #define IS_HATCH(s) ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH)
ab9d0a8c 92#endif
4bb6408c 93
ea76a6a5
WS
94// FIXME: left over after removal of wxDC::GetOptimization()
95#define GET_OPTIMIZATION false
96
af0bb3b1
VZ
97// ----------------------------------------------------------------------------
98// prototypes
99// ----------------------------------------------------------------------------
100
101static void XCopyRemote(Display *src_display, Display *dest_display,
102 Drawable src, Drawable dest,
103 GC destgc,
104 int srcx, int srcy,
105 unsigned int w, unsigned int h,
106 int destx, int desty,
107 bool more, XImage **cache);
108
109// ============================================================================
110// implementation
111// ============================================================================
112
95724b1a
VZ
113/*
114 * compare two doubles and return the larger rounded
115 * to the nearest int
116 */
117static int roundmax(double a, double b)
118{
119 return (int)((a > b ? a : b) + 0.5);
120}
121
122/*
123 * compare two doubles and return the smaller rounded
124 * to the nearest int
125 */
126static int roundmin(double a, double b)
127{
128 return (int)((a < b ? a : b) - 0.5);
129}
130
131
af0bb3b1
VZ
132// ----------------------------------------------------------------------------
133// wxWindowDC
134// ----------------------------------------------------------------------------
135
76208c7e 136void wxWindowDC::Init()
dfc54541
JS
137{
138 m_gc = (WXGC) 0;
139 m_gcBacking = (WXGC) 0;
140 m_window = NULL;
141 m_backgroundPixel = -1;
142 m_currentPenWidth = 1;
143 m_currentPenJoin = -1;
144 m_currentPenDashCount = -1;
69c44812 145 m_currentPenDash = (wxX11Dash*) NULL;
dfc54541
JS
146 m_currentStyle = -1;
147 m_currentFill = -1;
dfc54541
JS
148 m_colour = wxColourDisplay();
149 m_display = (WXDisplay*) NULL;
16c1f7f3
JS
150 m_pixmap = (WXPixmap) 0;
151 m_autoSetting = 0;
76208c7e 152 m_ok = false;
148b44a1 153 m_clipRegion = (WXRegion) 0;
76208c7e
MB
154}
155
156wxWindowDC::wxWindowDC()
157{
158 Init();
af0bb3b1 159}
dfc54541
JS
160
161wxWindowDC::wxWindowDC( wxWindow *window )
162{
16c1f7f3 163 wxASSERT_MSG( (window != (wxWindow*) NULL), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
af0bb3b1 164
76208c7e
MB
165 Init();
166
dfc54541 167 m_window = window;
60f5b880 168 m_font = window->GetFont();
ab9d0a8c 169 m_ok = true;
af0bb3b1 170
16c1f7f3
JS
171 m_display = window->GetXDisplay();
172 m_pixmap = window->GetXWindow();
173 Display* display = (Display*) m_display;
af0bb3b1 174
16c1f7f3 175 XSetWindowColormap (display, (Pixmap) m_pixmap, (Colormap) wxTheApp->GetMainColormap(m_display));
af0bb3b1 176
16c1f7f3
JS
177 XGCValues gcvalues;
178 gcvalues.foreground = BlackPixel (display, DefaultScreen (display));
179 gcvalues.background = WhitePixel (display, DefaultScreen (display));
180 gcvalues.graphics_exposures = False;
66eca538 181 gcvalues.subwindow_mode = IncludeInferiors;
16c1f7f3
JS
182 gcvalues.line_width = 1;
183 m_gc = (WXGC) XCreateGC (display, RootWindow (display, DefaultScreen (display)),
66eca538 184 GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode,
2d120f83 185 &gcvalues);
af0bb3b1 186
16c1f7f3
JS
187 if (m_window->GetBackingPixmap())
188 {
2d120f83
JS
189 m_gcBacking = (WXGC) XCreateGC (display, RootWindow (display,
190 DefaultScreen (display)),
66eca538 191 GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode,
2d120f83 192 &gcvalues);
16c1f7f3 193 }
af0bb3b1 194
16c1f7f3 195 m_backgroundPixel = (int) gcvalues.background;
af0bb3b1 196
a91b47e8 197 SetBackground(wxBrush(m_window->GetBackgroundColour(), wxSOLID));
af0bb3b1 198}
dfc54541 199
af0bb3b1 200wxWindowDC::~wxWindowDC()
dfc54541
JS
201{
202 if (m_gc)
203 XFreeGC ((Display*) m_display, (GC) m_gc);
204 m_gc = (WXGC) 0;
af0bb3b1 205
dfc54541
JS
206 if (m_gcBacking)
207 XFreeGC ((Display*) m_display, (GC) m_gcBacking);
208 m_gcBacking = (WXGC) 0;
af0bb3b1 209
148b44a1
MB
210 if (m_clipRegion)
211 XDestroyRegion ((Region) m_clipRegion);
212 m_clipRegion = (WXRegion) 0;
af0bb3b1 213}
dfc54541 214
ab9d0a8c 215extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
3a0a5ada 216 const wxColour & col, int style);
4bb6408c 217
387ebd3e 218bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y,
3a0a5ada
VS
219 const wxColour& col, int style)
220{
387ebd3e 221 return wxDoFloodFill(this, x, y, col, style);
b1699cd3 222}
ab9d0a8c 223
dc1efb1d 224bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
4bb6408c 225{
dc1efb1d
JS
226 // Generic (and therefore rather inefficient) method.
227 // Could be improved.
228 wxMemoryDC memdc;
229 wxBitmap bitmap(1, 1);
230 memdc.SelectObject(bitmap);
231 memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
232 memdc.SelectObject(wxNullBitmap);
79f1dd05 233 wxImage image = bitmap.ConvertToImage();
dc1efb1d 234 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
ab9d0a8c 235 return true;
af0bb3b1 236}
4bb6408c 237
7b65ea1a 238void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
4bb6408c 239{
af0bb3b1
VZ
240 wxCHECK_RET( Ok(), "invalid dc" );
241
2d120f83 242 int x1d, y1d, x2d, y2d;
af0bb3b1 243
2d120f83
JS
244 x1d = XLOG2DEV(x1);
245 y1d = YLOG2DEV(y1);
246 x2d = XLOG2DEV(x2);
247 y2d = YLOG2DEV(y2);
af0bb3b1 248
2d120f83
JS
249 if (m_autoSetting)
250 SetPen (m_pen);
af0bb3b1 251
2d120f83 252 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x1d, y1d, x2d, y2d);
af0bb3b1 253
2d120f83 254 if (m_window && m_window->GetBackingPixmap())
af0bb3b1 255 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
2d120f83
JS
256 XLOG2DEV_2(x1), YLOG2DEV_2(y1),
257 XLOG2DEV_2(x2), YLOG2DEV_2(y2));
af0bb3b1 258
2d120f83
JS
259 CalcBoundingBox(x1, y1);
260 CalcBoundingBox(x2, y2);
af0bb3b1 261}
4bb6408c 262
7b65ea1a 263void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
4bb6408c 264{
af0bb3b1
VZ
265 wxCHECK_RET( Ok(), "invalid dc" );
266
2d120f83
JS
267 if (m_autoSetting)
268 SetPen (m_pen);
af0bb3b1 269
2d120f83
JS
270 int xx = XLOG2DEV (x);
271 int yy = YLOG2DEV (y);
272 int ww, hh;
273 wxDisplaySize (&ww, &hh);
274 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, yy,
275 ww, yy);
276 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xx, 0,
277 xx, hh);
af0bb3b1 278
2d120f83 279 if (m_window && m_window->GetBackingPixmap())
16c1f7f3 280 {
2d120f83
JS
281 xx = XLOG2DEV_2 (x);
282 yy = YLOG2DEV_2 (y);
283 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
284 0, yy,
285 ww, yy);
286 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
287 xx, 0,
288 xx, hh);
16c1f7f3 289 }
af0bb3b1 290}
4bb6408c 291
7b65ea1a 292void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
4bb6408c 293{
af0bb3b1
VZ
294 wxCHECK_RET( Ok(), "invalid dc" );
295
2d120f83
JS
296 int xx1 = XLOG2DEV (x1);
297 int yy1 = YLOG2DEV (y1);
298 int xx2 = XLOG2DEV (x2);
299 int yy2 = YLOG2DEV (y2);
300 int xxc = XLOG2DEV (xc);
301 int yyc = YLOG2DEV (yc);
302 int xxc_2 = XLOG2DEV_2 (xc);
303 int yyc_2 = YLOG2DEV_2 (yc);
af0bb3b1 304
7b65ea1a
MB
305 wxCoord dx = xx1 - xxc;
306 wxCoord dy = yy1 - yyc;
f6bcfd97 307 double radius = sqrt ((double)(dx * dx + dy * dy));
7b65ea1a 308 wxCoord r = (wxCoord) radius;
af0bb3b1 309
2d120f83 310 double radius1, radius2;
af0bb3b1 311
2d120f83 312 if (xx1 == xx2 && yy1 == yy2)
16c1f7f3 313 {
2d120f83
JS
314 radius1 = 0.0;
315 radius2 = 360.0;
16c1f7f3 316 }
2d120f83
JS
317 else if (radius == 0.0)
318 radius1 = radius2 = 0.0;
16c1f7f3 319 else
2d120f83
JS
320 {
321 if (xx1 - xxc == 0)
322 if (yy1 - yyc < 0)
323 radius1 = 90.0;
324 else
325 radius1 = -90.0;
326 else
327 radius1 = -atan2 ((double) (yy1 - yyc), (double) (xx1 - xxc)) * 360.0 / (2 * M_PI);
af0bb3b1 328
2d120f83
JS
329 if (xx2 - xxc == 0)
330 if (yy2 - yyc < 0)
331 radius2 = 90.0;
332 else
333 radius2 = -90.0;
334 else
335 radius2 = -atan2 ((double) (yy2 - yyc), (double) (xx2 - xxc)) * 360.0 / (2 * M_PI);
16c1f7f3 336 }
2d120f83
JS
337 radius1 *= 64.0;
338 radius2 *= 64.0;
339 int alpha1 = (int) radius1;
340 int alpha2 = (int) (radius2 - radius1);
341 while (alpha2 <= 0)
342 alpha2 += 360 * 64;
343 while (alpha2 > 360 * 64)
344 alpha2 -= 360 * 64;
af0bb3b1 345
2d120f83 346 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
16c1f7f3 347 {
2d120f83
JS
348 SetBrush (m_brush);
349 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) (GC) m_gc,
350 xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2);
af0bb3b1 351
2d120f83
JS
352 if (m_window && m_window->GetBackingPixmap())
353 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
354 xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2);
af0bb3b1 355
16c1f7f3 356 }
af0bb3b1 357
2d120f83 358 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
16c1f7f3
JS
359 {
360 if (m_autoSetting)
361 SetPen (m_pen);
2d120f83
JS
362 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc,
363 xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2);
af0bb3b1 364
2d120f83
JS
365 if (m_window && m_window->GetBackingPixmap())
366 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
367 xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2);
16c1f7f3 368 }
2d120f83
JS
369 CalcBoundingBox (x1, y1);
370 CalcBoundingBox (x2, y2);
af0bb3b1 371}
4bb6408c 372
7b65ea1a 373void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
4bb6408c 374{
af0bb3b1
VZ
375 wxCHECK_RET( Ok(), "invalid dc" );
376
2d120f83 377 int xd, yd, wd, hd;
af0bb3b1 378
2d120f83
JS
379 xd = XLOG2DEV(x);
380 yd = YLOG2DEV(y);
381 wd = XLOG2DEVREL(width);
382 hd = YLOG2DEVREL(height);
af0bb3b1 383
2d120f83
JS
384 if (sa>=360 || sa<=-360) sa=sa-int(sa/360)*360;
385 if (ea>=360 || ea<=-360) ea=ea-int(ea/360)*360;
386 int start = int(sa*64);
387 int end = int(ea*64);
388 if (start<0) start+=360*64;
389 if (end <0) end +=360*64;
390 if (end>start) end-=start;
391 else end+=360*64-start;
af0bb3b1 392
2d120f83 393 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
16c1f7f3 394 {
96be256b 395 m_autoSetting = true; // must be reset
af0bb3b1 396
2d120f83
JS
397 SetBrush (m_brush);
398 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start, end);
af0bb3b1 399
2d120f83
JS
400 if (m_window && m_window->GetBackingPixmap())
401 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
402 XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end);
16c1f7f3 403 }
af0bb3b1 404
2d120f83 405 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
16c1f7f3 406 {
2d120f83
JS
407 if (m_autoSetting)
408 SetPen (m_pen);
409 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start,end);
410 if (m_window && m_window->GetBackingPixmap())
411 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
412 XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end);
16c1f7f3 413 }
2d120f83
JS
414 CalcBoundingBox (x, y);
415 CalcBoundingBox (x + width, y + height);
af0bb3b1 416}
4bb6408c 417
7b65ea1a 418void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
4bb6408c 419{
af0bb3b1
VZ
420 wxCHECK_RET( Ok(), "invalid dc" );
421
2d120f83
JS
422 if (m_pen.Ok() && m_autoSetting)
423 SetPen (m_pen);
af0bb3b1 424
2d120f83
JS
425 XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y));
426 if (m_window && m_window->GetBackingPixmap())
427 XDrawPoint ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, XLOG2DEV_2 (x), YLOG2DEV_2 (y));
af0bb3b1 428
2d120f83 429 CalcBoundingBox (x, y);
af0bb3b1 430}
4bb6408c 431
7b65ea1a 432void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
4bb6408c 433{
af0bb3b1
VZ
434 wxCHECK_RET( Ok(), "invalid dc" );
435
2d120f83 436 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
16c1f7f3 437 {
2d120f83
JS
438 if (m_autoSetting)
439 SetPen (m_pen);
af0bb3b1 440
2d120f83
JS
441 XPoint *xpoints = new XPoint[n];
442 int i;
af0bb3b1 443
2d120f83 444 for (i = 0; i < n; i++)
16c1f7f3 445 {
2d120f83
JS
446 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
447 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
448 }
449 XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints, n, 0);
af0bb3b1 450
2d120f83
JS
451 if (m_window && m_window->GetBackingPixmap())
452 {
453 for (i = 0; i < n; i++)
454 {
455 xpoints[i].x = XLOG2DEV_2 (points[i].x + xoffset);
456 xpoints[i].y = YLOG2DEV_2 (points[i].y + yoffset);
457 }
458 XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints, n, 0);
16c1f7f3 459 }
2d120f83 460 delete[]xpoints;
16c1f7f3 461 }
af0bb3b1 462}
4bb6408c 463
af0bb3b1 464void wxWindowDC::DoDrawPolygon( int n, wxPoint points[],
7b65ea1a 465 wxCoord xoffset, wxCoord yoffset, int fillStyle )
4bb6408c 466{
af0bb3b1 467 wxCHECK_RET( Ok(), "invalid dc" );
4bb6408c 468
2d120f83
JS
469 XPoint *xpoints1 = new XPoint[n + 1];
470 XPoint *xpoints2 = new XPoint[n + 1];
471 int i;
472 for (i = 0; i < n; i++)
16c1f7f3 473 {
2d120f83
JS
474 xpoints1[i].x = XLOG2DEV (points[i].x + xoffset);
475 xpoints1[i].y = YLOG2DEV (points[i].y + yoffset);
476 xpoints2[i].x = XLOG2DEV_2 (points[i].x + xoffset);
477 xpoints2[i].y = YLOG2DEV_2 (points[i].y + yoffset);
478 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
16c1f7f3 479 }
af0bb3b1 480
2d120f83
JS
481 // Close figure for XDrawLines (not needed for XFillPolygon)
482 xpoints1[i].x = xpoints1[0].x;
483 xpoints1[i].y = xpoints1[0].y;
484 xpoints2[i].x = xpoints2[0].x;
485 xpoints2[i].y = xpoints2[0].y;
af0bb3b1 486
2d120f83 487 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
16c1f7f3 488 {
2d120f83
JS
489 SetBrush (m_brush);
490 XSetFillRule ((Display*) m_display, (GC) m_gc, fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule);
491 XFillPolygon ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n, Complex, 0);
492 XSetFillRule ((Display*) m_display, (GC) m_gc, EvenOddRule); // default mode
493 if (m_window && m_window->GetBackingPixmap())
494 {
495 XSetFillRule ((Display*) m_display,(GC) m_gcBacking,
496 fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule);
497 XFillPolygon ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n, Complex, 0);
498 XSetFillRule ((Display*) m_display,(GC) m_gcBacking, EvenOddRule); // default mode
499 }
500 }
af0bb3b1 501
2d120f83 502 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
16c1f7f3 503 {
2d120f83
JS
504 if (m_autoSetting)
505 SetPen (m_pen);
506 XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n + 1, 0);
af0bb3b1 507
2d120f83
JS
508 if (m_window && m_window->GetBackingPixmap())
509 XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n + 1, 0);
16c1f7f3 510 }
af0bb3b1 511
2d120f83
JS
512 delete[]xpoints1;
513 delete[]xpoints2;
af0bb3b1 514}
4bb6408c 515
7b65ea1a 516void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
4bb6408c 517{
af0bb3b1 518 wxCHECK_RET( Ok(), "invalid dc" );
4bb6408c 519
2d120f83 520 int xd, yd, wfd, hfd, wd, hd;
af0bb3b1 521
2d120f83
JS
522 xd = XLOG2DEV(x);
523 yd = YLOG2DEV(y);
524 wfd = XLOG2DEVREL(width);
525 wd = wfd - WX_GC_CF;
526 hfd = YLOG2DEVREL(height);
527 hd = hfd - WX_GC_CF;
af0bb3b1 528
2d120f83
JS
529 if (wfd == 0 || hfd == 0) return;
530 if (wd < 0) { wd = - wd; xd = xd - wd; }
531 if (hd < 0) { hd = - hd; yd = yd - hd; }
af0bb3b1 532
2d120f83 533 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
16c1f7f3 534 {
2d120f83
JS
535 SetBrush (m_brush);
536 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wfd, hfd);
af0bb3b1 537
2d120f83
JS
538 if (m_window && m_window->GetBackingPixmap())
539 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
16c1f7f3
JS
540 XLOG2DEV_2 (x), YLOG2DEV_2 (y),
541 wfd, hfd);
542 }
af0bb3b1 543
2d120f83 544 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
16c1f7f3 545 {
2d120f83
JS
546 if (m_autoSetting)
547 SetPen (m_pen);
548 XDrawRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd);
af0bb3b1 549
2d120f83
JS
550 if (m_window && m_window->GetBackingPixmap())
551 XDrawRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
16c1f7f3
JS
552 XLOG2DEV_2 (x), YLOG2DEV_2 (y),
553 wd, hd);
554 }
2d120f83
JS
555 CalcBoundingBox (x, y);
556 CalcBoundingBox (x + width, y + height);
af0bb3b1 557}
4bb6408c 558
7b65ea1a 559void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
4bb6408c 560{
af0bb3b1
VZ
561 wxCHECK_RET( Ok(), "invalid dc" );
562
2d120f83 563 // If radius is negative, it's a proportion of the smaller dimension.
af0bb3b1 564
2d120f83 565 if (radius < 0.0) radius = - radius * ((width < height) ? width : height);
af0bb3b1 566
2d120f83
JS
567 int xd = XLOG2DEV (x);
568 int yd = YLOG2DEV (y);
569 int rd = XLOG2DEVREL ((long) radius);
570 int wd = XLOG2DEVREL (width) - WX_GC_CF;
571 int hd = YLOG2DEVREL (height) - WX_GC_CF;
af0bb3b1 572
2d120f83
JS
573 int rw_d = rd * 2;
574 int rh_d = rw_d;
af0bb3b1 575
2d120f83
JS
576 // If radius is zero use DrawRectangle() instead to avoid
577 // X drawing errors with small radii
578 if (rd == 0)
16c1f7f3 579 {
2d120f83
JS
580 DrawRectangle( x, y, width, height );
581 return;
16c1f7f3 582 }
af0bb3b1 583
2d120f83
JS
584 // Draw nothing if transformed w or h is 0
585 if (wd == 0 || hd == 0) return;
af0bb3b1 586
2d120f83
JS
587 // CMB: adjust size if outline is drawn otherwise the result is
588 // 1 pixel too wide and high
589 if (m_pen.GetStyle() != wxTRANSPARENT)
16c1f7f3 590 {
2d120f83
JS
591 wd--;
592 hd--;
16c1f7f3 593 }
af0bb3b1 594
2d120f83
JS
595 // CMB: ensure dd is not larger than rectangle otherwise we
596 // get an hour glass shape
597 if (rw_d > wd) rw_d = wd;
598 if (rw_d > hd) rw_d = hd;
599 rd = rw_d / 2;
af0bb3b1 600
2d120f83
JS
601 // For backing pixmap
602 int xd2 = XLOG2DEV_2 (x);
603 int yd2 = YLOG2DEV_2 (y);
604 int rd2 = XLOG2DEVREL ((long) radius);
605 int wd2 = XLOG2DEVREL (width) ;
606 int hd2 = YLOG2DEVREL (height) ;
af0bb3b1 607
2d120f83
JS
608 int rw_d2 = rd2 * 2;
609 int rh_d2 = rw_d2;
af0bb3b1 610
2d120f83
JS
611 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
612 {
613 SetBrush (m_brush);
af0bb3b1 614
2d120f83
JS
615 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd,
616 wd - rw_d, hd);
617 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd,
618 wd, hd - rh_d);
af0bb3b1 619
2d120f83
JS
620 // Arcs start from 3 o'clock, positive angles anticlockwise
621 // Top-left
622 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd,
623 rw_d, rh_d, 90 * 64, 90 * 64);
624 // Top-right
625 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd,
626 // rw_d, rh_d, 0, 90 * 64);
627 rw_d, rh_d, 0, 91 * 64);
628 // Bottom-right
629 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d,
630 yd + hd - rh_d,
631 // rw_d, rh_d, 270 * 64, 90 * 64);
632 rw_d, rh_d, 269 * 64, 92 * 64);
633 // Bottom-left
634 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d,
635 rw_d, rh_d, 180 * 64, 90 * 64);
af0bb3b1 636
2d120f83
JS
637 if (m_window && m_window->GetBackingPixmap())
638 {
639 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
640 xd2 + rd2, yd2, wd2 - rw_d2, hd2);
641 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
642 xd2, yd2 + rd2, wd2, hd2 - rh_d2);
af0bb3b1 643
2d120f83
JS
644 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
645 xd2, yd2, rw_d2, rh_d2, 90 * 64, 90 * 64);
646 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
647 xd2 + wd2 - rw_d2, yd2,
648 // rw_d2, rh_d2, 0, 90 * 64);
649 rw_d2, rh_d2, 0, 91 * 64);
650 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
651 xd2 + wd2 - rw_d2,
652 yd2 + hd2 - rh_d2,
653 // rw_d2, rh_d2, 270 * 64, 90 * 64);
654 rw_d2, rh_d2, 269 * 64, 92 * 64);
655 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
656 xd2, yd2 + hd2 - rh_d2,
657 rw_d2, rh_d2, 180 * 64, 90 * 64);
658 }
659 }
af0bb3b1 660
2d120f83
JS
661 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
662 {
663 SetPen (m_pen);
664 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd,
665 xd + wd - rd + 1, yd);
666 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd + hd,
667 xd + wd - rd, yd + hd);
af0bb3b1 668
2d120f83
JS
669 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd,
670 xd, yd + hd - rd);
671 XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd, yd + rd,
672 xd + wd, yd + hd - rd + 1);
673 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd,
674 rw_d, rh_d, 90 * 64, 90 * 64);
675 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd,
676 // rw_d, rh_d, 0, 90 * 64);
677 rw_d, rh_d, 0, 91 * 64);
678 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d,
679 yd + hd - rh_d,
680 rw_d, rh_d, 269 * 64, 92 * 64);
681 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d,
682 rw_d, rh_d, 180 * 64, 90 * 64);
af0bb3b1 683
2d120f83
JS
684 if (m_window && m_window->GetBackingPixmap())
685 {
686 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
687 xd2 + rd2, yd2,
688 xd2 + wd2 - rd2 + 1, yd2);
689 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
690 xd2 + rd2, yd2 + hd2,
691 xd2 + wd2 - rd2, yd2 + hd2);
af0bb3b1 692
2d120f83
JS
693 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
694 xd2, yd2 + rd2,
695 xd2, yd2 + hd2 - rd2);
696 XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
697 xd2 + wd2, yd2 + rd2,
698 xd2 + wd2, yd2 + hd2 - rd2 + 1);
699 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
700 xd2, yd2,
701 rw_d2, rh_d2, 90 * 64, 90 * 64);
702 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
703 xd2 + wd2 - rw_d2, yd2,
704 // rw_d2, rh_d2, 0, 90 * 64);
705 rw_d2, rh_d2, 0, 91 * 64);
706 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
707 xd2 + wd2 - rw_d2,
708 yd2 + hd2 - rh_d2,
709 rw_d2, rh_d2, 269 * 64, 92 * 64);
710 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
711 xd2, yd2 + hd2 - rh_d2,
712 rw_d2, rh_d2, 180 * 64, 90 * 64);
713 }
714 }
715 CalcBoundingBox (x, y);
716 CalcBoundingBox (x + width, y + height);
af0bb3b1
VZ
717}
718
7b65ea1a 719void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
4bb6408c 720{
af0bb3b1
VZ
721 wxCHECK_RET( Ok(), "invalid dc" );
722
2d120f83
JS
723 // Check for negative width and height
724 if (height < 0)
16c1f7f3 725 {
2d120f83
JS
726 y = y + height;
727 height = - height ;
16c1f7f3 728 }
af0bb3b1 729
2d120f83 730 if (width < 0)
16c1f7f3 731 {
2d120f83
JS
732 x = x + width;
733 width = - width ;
16c1f7f3 734 }
af0bb3b1 735
2d120f83 736 static const int angle = 23040;
af0bb3b1 737
2d120f83 738 int xd, yd, wd, hd;
af0bb3b1 739
2d120f83
JS
740 xd = XLOG2DEV(x);
741 yd = YLOG2DEV(y);
742 wd = XLOG2DEVREL(width) ;
743 hd = YLOG2DEVREL(height) ;
af0bb3b1 744
2d120f83
JS
745 if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
746 {
747 SetBrush (m_brush);
748 XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle);
749 if (m_window && m_window->GetBackingPixmap())
750 XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
751 XLOG2DEV_2 (x), YLOG2DEV_2 (y),
752 XLOG2DEVREL (width) - WX_GC_CF,
753 YLOG2DEVREL (height) - WX_GC_CF, 0, angle);
754 }
af0bb3b1 755
2d120f83
JS
756 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
757 {
758 if (m_autoSetting)
759 SetPen (m_pen);
760 XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle);
761 if (m_window && m_window->GetBackingPixmap())
762 XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
763 XLOG2DEV_2 (x), YLOG2DEV_2 (y),
764 XLOG2DEVREL (width) - WX_GC_CF,
765 YLOG2DEVREL (height) - WX_GC_CF, 0, angle);
766 }
767 CalcBoundingBox (x, y);
768 CalcBoundingBox (x + width, y + height);
4bb6408c 769
af0bb3b1 770}
16c1f7f3 771
af0bb3b1 772bool wxWindowDC::CanDrawBitmap() const
16c1f7f3 773{
ab9d0a8c 774 wxCHECK_MSG( Ok(), false, "invalid dc" );
af0bb3b1 775
ab9d0a8c 776 return true;
16c1f7f3
JS
777}
778
ab9d0a8c 779// TODO: use scaled Blit e.g. as per John Price's implementation
148b44a1
MB
780// in Contrib/Utilities
781bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
782 wxCoord width, wxCoord height,
783 wxDC *source, wxCoord xsrc, wxCoord ysrc,
784 int rop, bool useMask,
0cbff120 785 wxCoord xsrcMask, wxCoord ysrcMask )
2d120f83 786{
ab9d0a8c 787 wxCHECK_MSG( Ok(), false, "invalid dc" );
af0bb3b1
VZ
788
789 wxWindowDC* sourceDC = wxDynamicCast(source, wxWindowDC);
790
791 wxASSERT_MSG( sourceDC, "Blit source DC must be wxWindowDC or derived class." );
792
395539f9
MB
793 // Be sure that foreground pixels (1) of the Icon will be painted with
794 // foreground colour. [m_textForegroundColour] Background pixels (0)
795 // will be painted with backgound colour (m_textBackgroundColour)
796 // Using ::SetPen is horribly slow, so avoid doing it
797 int oldBackgroundPixel = -1;
798 int oldForegroundPixel = -1;
799
800 if (m_textBackgroundColour.Ok())
801 {
802 oldBackgroundPixel = m_backgroundPixel;
803 int pixel = m_textBackgroundColour.AllocColour(m_display);
804
805 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
806 if (m_window && m_window->GetBackingPixmap())
807 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
808 pixel);
809 }
810 if (m_textForegroundColour.Ok())
811 {
812 oldForegroundPixel = m_currentColour.GetPixel();
813
814 if( m_textForegroundColour.GetPixel() <= -1 )
815 CalculatePixel( m_textForegroundColour,
ab9d0a8c
WS
816 m_textForegroundColour, true);
817
395539f9
MB
818 int pixel = m_textForegroundColour.GetPixel();
819 if (pixel > -1)
820 SetForegroundPixelWithLogicalFunction(pixel);
821 }
a91b47e8
JS
822
823 // Do bitmap scaling if necessary
824
825 wxBitmap *scaledBitmap = (wxBitmap*) NULL;
826 Pixmap sourcePixmap = (Pixmap) NULL;
827 double scaleX, scaleY;
828 GetUserScale(& scaleX, & scaleY);
ab9d0a8c 829 bool retVal = false;
a91b47e8 830
0cbff120
JS
831 /* TODO: use the mask origin when drawing transparently */
832 if (xsrcMask == -1 && ysrcMask == -1)
833 {
834 xsrcMask = xsrc; ysrcMask = ysrc;
835 }
836
a91b47e8
JS
837 // Sorry, can't scale masks just yet
838 if (!useMask && (scaleX != 1.0 || scaleY != 1.0) && sourceDC->IsKindOf(CLASSINFO(wxMemoryDC)))
839 {
840 wxMemoryDC* memDC = (wxMemoryDC*) sourceDC;
841 wxBitmap& bitmap = memDC->GetBitmap();
842
843 wxASSERT_MSG( (bitmap.Ok()), "Bad source bitmap in wxWindowDC::Blit");
844
79f1dd05 845 wxImage image = bitmap.ConvertToImage();
a91b47e8
JS
846 if (!image.Ok())
847 {
aae0472b 848 sourcePixmap = (Pixmap) bitmap.GetDrawable();
a91b47e8
JS
849 }
850 else
851 {
852 int scaledW = (int) (bitmap.GetWidth() * scaleX);
853 int scaledH = (int) (bitmap.GetHeight() * scaleY);
af0bb3b1 854
a91b47e8 855 image = image.Scale(scaledW, scaledH);
79f1dd05 856 scaledBitmap = new wxBitmap(image);
aae0472b 857 sourcePixmap = (Pixmap) scaledBitmap->GetDrawable();
af0bb3b1 858 }
a91b47e8
JS
859 }
860 else
861 sourcePixmap = (Pixmap) sourceDC->m_pixmap;
862
863 if (m_pixmap && sourcePixmap)
2d120f83
JS
864 {
865 /* MATTHEW: [9] */
866 int orig = m_logicalFunction;
af0bb3b1 867
2d120f83 868 SetLogicalFunction (rop);
af0bb3b1 869
2d120f83
JS
870 if (m_display != sourceDC->m_display)
871 {
872 XImage *cache = NULL;
af0bb3b1 873
2d120f83
JS
874 if (m_window && m_window->GetBackingPixmap())
875 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display,
a91b47e8 876 (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),
2d120f83
JS
877 (GC) m_gcBacking,
878 source->LogicalToDeviceX (xsrc),
879 source->LogicalToDeviceY (ysrc),
880 source->LogicalToDeviceXRel(width),
881 source->LogicalToDeviceYRel(height),
882 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest),
f29aaf78 883 True, &cache);
af0bb3b1 884
2d120f83
JS
885 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
886 {
887 wxMemoryDC *memDC = (wxMemoryDC *)source;
888 wxBitmap& sel = memDC->GetBitmap();
aae0472b 889 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetBitmap() )
2d120f83 890 {
aae0472b 891 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap());
2d120f83
JS
892 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
893 }
894 }
af0bb3b1 895
a91b47e8 896 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
2d120f83
JS
897 source->LogicalToDeviceX (xsrc),
898 source->LogicalToDeviceY (ysrc),
899 source->LogicalToDeviceXRel(width),
900 source->LogicalToDeviceYRel(height),
901 XLOG2DEV (xdest), YLOG2DEV (ydest),
96be256b 902 False, &cache);
af0bb3b1 903
2d120f83
JS
904 if ( useMask )
905 {
148b44a1
MB
906 if ( m_clipRegion )
907 XSetRegion ((Display*) m_display, (GC) m_gc,
908 (Region) m_clipRegion);
909 else
910 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
911
2d120f83
JS
912 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
913 }
af0bb3b1 914
2d120f83 915 } else
395539f9 916 { //XGCValues values;
ab9d0a8c 917 //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
395539f9 918
2d120f83
JS
919 if (m_window && m_window->GetBackingPixmap())
920 {
921 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
922 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetBitmap().GetDepth() == 1)
923 {
a91b47e8 924 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
2d120f83
JS
925 source->LogicalToDeviceX (xsrc),
926 source->LogicalToDeviceY (ysrc),
927 source->LogicalToDeviceXRel(width),
928 source->LogicalToDeviceYRel(height),
929 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1);
930 }
931 else
932 {
a91b47e8 933 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
2d120f83
JS
934 source->LogicalToDeviceX (xsrc),
935 source->LogicalToDeviceY (ysrc),
936 source->LogicalToDeviceXRel(width),
937 source->LogicalToDeviceYRel(height),
938 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest));
939 }
940 }
941 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
942 {
943 wxMemoryDC *memDC = (wxMemoryDC *)source;
944 wxBitmap& sel = memDC->GetBitmap();
aae0472b 945 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetBitmap() )
2d120f83 946 {
aae0472b 947 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap());
2d120f83
JS
948 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
949 }
950 }
af0bb3b1 951
2d120f83
JS
952 // Check if we're copying from a mono bitmap
953 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) &&
954 ((wxMemoryDC*)source)->GetBitmap().Ok() && (((wxMemoryDC*)source)->GetBitmap().GetDepth () == 1))
955 {
a91b47e8 956 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
2d120f83
JS
957 source->LogicalToDeviceX (xsrc),
958 source->LogicalToDeviceY (ysrc),
959 source->LogicalToDeviceXRel(width),
960 source->LogicalToDeviceYRel(height),
961 XLOG2DEV (xdest), YLOG2DEV (ydest), 1);
962 }
963 else
964 {
a91b47e8 965 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
2d120f83
JS
966 source->LogicalToDeviceX (xsrc),
967 source->LogicalToDeviceY (ysrc),
968 source->LogicalToDeviceXRel(width),
969 source->LogicalToDeviceYRel(height),
970 XLOG2DEV (xdest), YLOG2DEV (ydest));
af0bb3b1 971
2d120f83
JS
972 }
973 if ( useMask )
974 {
148b44a1
MB
975 if ( m_clipRegion )
976 XSetRegion ((Display*) m_display, (GC) m_gc,
977 (Region) m_clipRegion);
978 else
979 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
980
2d120f83
JS
981 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
982 }
af0bb3b1 983
2d120f83
JS
984 } /* Remote/local (Display*) m_display */
985 CalcBoundingBox (xdest, ydest);
986 CalcBoundingBox (xdest + width, ydest + height);
af0bb3b1 987
2d120f83 988 SetLogicalFunction(orig);
a91b47e8 989
ab9d0a8c 990 retVal = true;
16c1f7f3 991 }
a91b47e8
JS
992 if (scaledBitmap) delete scaledBitmap;
993
395539f9
MB
994 if (oldBackgroundPixel > -1)
995 {
996 XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
997 if (m_window && m_window->GetBackingPixmap())
998 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
999 oldBackgroundPixel);
1000 }
1001 if (oldForegroundPixel > -1)
1002 {
1003 XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1004 if (m_window && m_window->GetBackingPixmap())
1005 XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1006 oldForegroundPixel);
1007 }
1008
1009 return retVal;
16c1f7f3
JS
1010}
1011
7b65ea1a 1012void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
4bb6408c 1013{
af0bb3b1
VZ
1014 wxCHECK_RET( Ok(), "invalid dc" );
1015
1016 // Since X draws from the baseline of the text, must add the text height
2d120f83
JS
1017 int cx = 0;
1018 int cy = 0;
1019 int ascent = 0;
996994c7 1020 int slen = text.length();
af0bb3b1 1021
2b830c41
MB
1022 // Set FillStyle, otherwise X will use current stipple!
1023 XGCValues gcV, gcBackingV;
1024
1025 XGetGCValues ((Display*) m_display, (GC)m_gc, GCFillStyle, &gcV);
1026 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1027 if (m_window && m_window->GetBackingPixmap())
1028 {
1029 XGetGCValues ((Display*) m_display, (GC)m_gcBacking, GCFillStyle,
1030 &gcBackingV );
1031 XSetFillStyle ((Display*) m_display, (GC) m_gcBacking, FillSolid);
1032 }
1033
2d120f83 1034 if (m_font.Ok())
996994c7
MB
1035 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1036 text, &cx, &cy, &ascent, NULL);
af0bb3b1
VZ
1037
1038 // First draw a rectangle representing the text background, if a text
1039 // background is specified
2d120f83 1040 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
16c1f7f3 1041 {
2d120f83 1042 wxColour oldPenColour = m_currentColour;
16c1f7f3 1043 m_currentColour = m_textBackgroundColour;
2d120f83
JS
1044 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1045 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1046 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1047 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
af0bb3b1 1048
2d120f83
JS
1049 // This separation of the big && test required for gcc2.7/HP UX 9.02
1050 // or pixel value can be corrupted!
1051 sameColour = (sameColour &&
1052 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
af0bb3b1 1053
ea76a6a5 1054 if (!sameColour || !GET_OPTIMIZATION)
16c1f7f3 1055 {
2d120f83
JS
1056 int pixel = m_textBackgroundColour.AllocColour(m_display);
1057 m_currentColour = m_textBackgroundColour;
af0bb3b1 1058
2d120f83
JS
1059 // Set the GC to the required colour
1060 if (pixel > -1)
1061 {
1062 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1063 if (m_window && m_window->GetBackingPixmap())
1064 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1065 }
16c1f7f3 1066 }
2d120f83
JS
1067 else
1068 m_textBackgroundColour = oldPenColour ;
af0bb3b1 1069
2d120f83
JS
1070 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1071 if (m_window && m_window->GetBackingPixmap())
1072 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
16c1f7f3
JS
1073 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1074 }
af0bb3b1 1075
2d120f83
JS
1076 // Now set the text foreground and draw the text
1077 if (m_textForegroundColour.Ok ())
1078 {
1079 wxColour oldPenColour = m_currentColour;
1080 m_currentColour = m_textForegroundColour;
1081 bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () &&
1082 (oldPenColour.Red () == m_currentColour.Red ()) &&
1083 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1084 (oldPenColour.Green () == m_currentColour.Green ()) &&
1085 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1086
ea76a6a5 1087 if (!sameColour || !GET_OPTIMIZATION)
16c1f7f3 1088 {
395539f9 1089 int pixel = CalculatePixel(m_textForegroundColour,
ab9d0a8c 1090 m_currentColour, false);
af0bb3b1 1091
2d120f83
JS
1092 // Set the GC to the required colour
1093 if (pixel > -1)
1094 {
1095 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1096 if (m_window && m_window->GetBackingPixmap())
1097 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1098 }
16c1f7f3
JS
1099 }
1100 else
2d120f83
JS
1101 m_textForegroundColour = oldPenColour;
1102 }
af0bb3b1
VZ
1103
1104 // We need to add the ascent, not the whole height, since X draws at the
1105 // point above the descender.
1106#if 0
16c1f7f3 1107 if (use16)
af0bb3b1 1108 XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
2d120f83
JS
1109 (XChar2b *)(char*) (const char*) text, slen);
1110 else
af0bb3b1 1111#endif // 0
996994c7
MB
1112#if wxMOTIF_NEW_FONT_HANDLING
1113 XFontSet fset = (XFontSet) m_font.GetFontSet (m_userScaleY * m_logicalScaleY, m_display);
1114 XmbDrawString((Display*) m_display, (Pixmap) m_pixmap, fset, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1115#else
af0bb3b1 1116 XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
996994c7 1117#endif
af0bb3b1 1118
2d120f83 1119 if (m_window && m_window->GetBackingPixmap()) {
af0bb3b1 1120#if 0
2d120f83
JS
1121 if (use16)
1122 XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
16c1f7f3
JS
1123 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1124 (XChar2b *)(char*) (const char*) text, slen);
2d120f83 1125 else
af0bb3b1 1126#endif // 0
996994c7
MB
1127#if wxMOTIF_NEW_FONT_HANDLING
1128 XmbDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), fset, (GC) m_gcBacking,
1129 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1130 wxConstCast(text.c_str(), char), slen);
1131#else
2d120f83 1132 XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
d3a80c92
MB
1133 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1134 wxConstCast(text.c_str(), char), slen);
996994c7 1135#endif
2d120f83 1136 }
af0bb3b1 1137
2b830c41
MB
1138 // restore fill style
1139 XSetFillStyle ((Display*) m_display, (GC) m_gc, gcV.fill_style);
1140 if (m_window && m_window->GetBackingPixmap())
1141 XSetFillStyle ((Display*) m_display, (GC) m_gcBacking,
1142 gcBackingV.fill_style);
1143
7b65ea1a 1144 wxCoord w, h;
2d120f83
JS
1145 GetTextExtent (text, &w, &h);
1146 CalcBoundingBox (x + w, y + h);
1147 CalcBoundingBox (x, y);
af0bb3b1 1148}
4bb6408c 1149
729be74d
MB
1150void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y,
1151 double angle )
95724b1a
VZ
1152{
1153 if (angle == 0.0)
1154 {
1155 DrawText(text, x, y);
1156 return;
1157 }
1158
1159 wxCHECK_RET( Ok(), "invalid dc" );
1160
729be74d
MB
1161 int oldBackgroundPixel = -1;
1162 int oldForegroundPixel = -1;
1163 int foregroundPixel = -1;
1164 int backgroundPixel = -1;
1165
1166 if (m_textBackgroundColour.Ok())
1167 {
1168 oldBackgroundPixel = m_backgroundPixel;
1169 backgroundPixel = m_textBackgroundColour.AllocColour(m_display);
1170 }
1171 if (m_textForegroundColour.Ok())
1172 {
1173 oldForegroundPixel = m_currentColour.GetPixel();
1174
1175 if( m_textForegroundColour.GetPixel() <= -1 )
1176 CalculatePixel( m_textForegroundColour,
ab9d0a8c
WS
1177 m_textForegroundColour, true);
1178
729be74d
MB
1179 foregroundPixel = m_textForegroundColour.GetPixel();
1180 }
1181
95724b1a
VZ
1182 // Since X draws from the baseline of the text, must add the text height
1183 int cx = 0;
1184 int cy = 0;
1185 int ascent = 0;
95724b1a
VZ
1186
1187 if (m_font.Ok())
996994c7
MB
1188 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1189 text, &cx, &cy, &ascent, NULL);
95724b1a
VZ
1190
1191 wxBitmap src(cx, cy);
1192 wxMemoryDC dc;
1193 dc.SelectObject(src);
1194 dc.SetFont(GetFont());
1195 dc.SetBackground(*wxWHITE_BRUSH);
1196 dc.SetBrush(*wxBLACK_BRUSH);
1197 dc.Clear();
1198 dc.DrawText(text, 0, 0);
1199 dc.SetFont(wxNullFont);
1200
1201 // Calculate the size of the rotated bounding box.
1202 double dx = cos(angle / 180.0 * M_PI);
1203 double dy = sin(angle / 180.0 * M_PI);
729be74d 1204 double x4 = cy * dy;
95724b1a
VZ
1205 double y4 = cy * dx;
1206 double x3 = cx * dx;
729be74d 1207 double y3 = -cx * dy;
95724b1a
VZ
1208 double x2 = x3 + x4;
1209 double y2 = y3 + y4;
1210 double x1 = x;
1211 double y1 = y;
1212
1213 // Create image from the source bitmap after writing the text into it.
79f1dd05 1214 wxImage image = src.ConvertToImage();
95724b1a
VZ
1215
1216 int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
1217 int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
1218 int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
1219 int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
1220
729be74d
MB
1221 bool lastFore = false, lastBack = false;
1222
95724b1a
VZ
1223 // This rotates counterclockwise around the top left corner.
1224 for (int rx = minx; rx < maxx; rx++)
1225 {
1226 for (int ry = miny; ry < maxy; ry++)
1227 {
1228 // transform dest coords to source coords
729be74d
MB
1229 int sx = (int) (rx * dx - ry * dy + 0.5);
1230 int sy = - (int) (-ry * dx - rx * dy + 0.5);
95724b1a
VZ
1231 if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
1232 {
729be74d
MB
1233 bool textPixel = image.GetRed(sx, sy) == 0;
1234
1235 if (!textPixel && m_backgroundMode != wxSOLID)
1236 continue;
1237
1238 wxCoord ox = (wxCoord) (x1 + rx),
1239 oy = (wxCoord) (y1 + ry);
95724b1a 1240 // draw black pixels, ignore white ones (i.e. transparent b/g)
729be74d 1241 if (textPixel && !lastFore)
95724b1a 1242 {
729be74d
MB
1243 XSetForeground ((Display*) m_display, (GC) m_gc,
1244 foregroundPixel);
1245 lastFore = true;
1246 lastBack = false;
95724b1a 1247 }
729be74d 1248 else if (!textPixel && !lastBack)
95724b1a 1249 {
729be74d
MB
1250 XSetForeground ((Display*) m_display, (GC) m_gc,
1251 backgroundPixel);
1252 lastFore = false;
1253 lastBack = true;
95724b1a 1254 }
95724b1a 1255
729be74d
MB
1256 XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap,
1257 (GC) m_gc, XLOG2DEV (ox), YLOG2DEV (oy));
95724b1a 1258 if (m_window && m_window->GetBackingPixmap())
729be74d
MB
1259 XDrawPoint ((Display*) m_display,
1260 (Pixmap) m_window->GetBackingPixmap(),
1261 (GC) m_gcBacking,
1262 XLOG2DEV_2 (ox), YLOG2DEV_2 (oy));
95724b1a
VZ
1263 }
1264 }
729be74d 1265 }
95724b1a 1266
729be74d
MB
1267 if (oldBackgroundPixel > -1)
1268 {
1269 XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
95724b1a 1270 if (m_window && m_window->GetBackingPixmap())
729be74d
MB
1271 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1272 oldBackgroundPixel);
1273 }
1274 if (oldForegroundPixel > -1)
1275 {
1276 XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1277 if (m_window && m_window->GetBackingPixmap())
1278 XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1279 oldForegroundPixel);
95724b1a 1280 }
95724b1a 1281
729be74d
MB
1282 CalcBoundingBox (minx, miny);
1283 CalcBoundingBox (maxx, maxy);
95724b1a
VZ
1284}
1285
af0bb3b1 1286bool wxWindowDC::CanGetTextExtent() const
4bb6408c 1287{
ab9d0a8c 1288 return true;
af0bb3b1 1289}
4bb6408c 1290
7b65ea1a
MB
1291void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1292 wxCoord *descent, wxCoord *externalLeading,
af0bb3b1 1293 wxFont *font ) const
4bb6408c 1294{
af0bb3b1
VZ
1295 wxCHECK_RET( Ok(), "invalid dc" );
1296
996994c7 1297 const wxFont* theFont = font ? font : &m_font;
af0bb3b1 1298
2d120f83
JS
1299 if (!theFont->Ok())
1300 {
1301 // TODO: this should be an error log function
1302 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
af0bb3b1 1303
33caefb3
RR
1304 if (width) *width = -1;
1305 if (height) *height = -1;
2d120f83
JS
1306 return;
1307 }
af0bb3b1 1308
996994c7
MB
1309 wxGetTextExtent(m_display, *theFont, m_userScaleY * m_logicalScaleY,
1310 string, width, height, NULL, descent);
af0bb3b1 1311
996994c7
MB
1312 if (width) *width = XDEV2LOGREL (*width);
1313 if (height) *height = YDEV2LOGREL (*height);
2d120f83
JS
1314 if (externalLeading)
1315 *externalLeading = 0;
af0bb3b1 1316}
4bb6408c 1317
7b65ea1a 1318wxCoord wxWindowDC::GetCharWidth() const
4bb6408c 1319{
af0bb3b1
VZ
1320 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1321 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
996994c7
MB
1322
1323 int width;
af0bb3b1 1324
996994c7
MB
1325 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1326 "x", &width, NULL, NULL, NULL);
af0bb3b1 1327
996994c7 1328 return XDEV2LOGREL(width);
af0bb3b1 1329}
4bb6408c 1330
7b65ea1a 1331wxCoord wxWindowDC::GetCharHeight() const
4bb6408c 1332{
af0bb3b1
VZ
1333 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1334 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1335
996994c7 1336 int height;
af0bb3b1 1337
996994c7
MB
1338 wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1339 "x", NULL, &height, NULL, NULL);
1340
1341 return XDEV2LOGREL(height);
af0bb3b1 1342}
4bb6408c 1343
76208c7e 1344void wxWindowDC::DoGetSize( int *width, int *height ) const
4bb6408c 1345{
76208c7e 1346 int w = 0, h = 0;
af0bb3b1 1347
76208c7e 1348 if( m_window )
16c1f7f3 1349 {
76208c7e 1350 if( m_window->GetBackingPixmap() )
2d120f83
JS
1351 {
1352 w = m_window->GetPixmapWidth();
1353 h = m_window->GetPixmapHeight();
1354 }
16c1f7f3 1355 else
76208c7e 1356 m_window->GetSize( &w, &h );
16c1f7f3 1357 }
af0bb3b1 1358
76208c7e
MB
1359 if( width ) *width = w;
1360 if( height ) *height = h;
1361}
af0bb3b1 1362
76208c7e
MB
1363void wxWindowDC::Clear()
1364{
1365 wxCHECK_RET( Ok(), "invalid dc" );
af0bb3b1 1366
3f0785de 1367 wxRect rect( GetSize() );
76208c7e 1368 Clear( rect );
af0bb3b1 1369}
4bb6408c 1370
a367b9b3
JS
1371void wxWindowDC::Clear(const wxRect& rect)
1372{
af0bb3b1
VZ
1373 wxCHECK_RET( Ok(), "invalid dc" );
1374
2d120f83
JS
1375 int x = rect.x; int y = rect.y;
1376 int w = rect.width; int h = rect.height;
af0bb3b1 1377
2d120f83
JS
1378 wxBrush saveBrush = m_brush;
1379 SetBrush (m_backgroundBrush);
af0bb3b1 1380
76208c7e
MB
1381 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc,
1382 x, y, w, h);
af0bb3b1 1383
2d120f83 1384 if (m_window && m_window->GetBackingPixmap())
76208c7e
MB
1385 XFillRectangle ((Display*) m_display,
1386 (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1387 x, y, w, h);
af0bb3b1 1388
2d120f83 1389 m_brush = saveBrush;
af0bb3b1 1390}
a367b9b3 1391
dfc54541 1392void wxWindowDC::SetFont( const wxFont &font )
4bb6408c 1393{
af0bb3b1
VZ
1394 wxCHECK_RET( Ok(), "invalid dc" );
1395
2d120f83 1396 m_font = font;
af0bb3b1 1397
2d120f83 1398 if (!m_font.Ok())
e97f20a0 1399 {
2d120f83 1400 return;
e97f20a0 1401 }
af0bb3b1 1402
996994c7 1403#if !wxMOTIF_NEW_FONT_HANDLING
2d120f83 1404 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
af0bb3b1 1405
2d120f83
JS
1406 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1407 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
af0bb3b1 1408
2d120f83
JS
1409 if (m_window && m_window->GetBackingPixmap())
1410 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
996994c7 1411#endif
af0bb3b1 1412}
4bb6408c 1413
395539f9
MB
1414void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel)
1415{
1416 if (m_logicalFunction == wxXOR)
1417 {
1418 XGCValues values;
1419 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1420 XSetForeground ((Display*) m_display, (GC) m_gc,
1421 pixel ^ values.background);
1422 if (m_window && m_window->GetBackingPixmap())
1423 XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1424 pixel ^ values.background);
1425 }
1426 else
1427 {
1428 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1429 if (m_window && m_window->GetBackingPixmap())
1430 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1431 }
1432}
1433
1434int wxWindowDC::CalculatePixel(wxColour& colour, wxColour& curCol,
1435 bool roundToWhite) const
1436{
1437 const unsigned char wp = (unsigned char)255;
ab9d0a8c 1438
395539f9
MB
1439 int pixel = -1;
1440 if(!m_colour) // Mono display
1441 {
1442 unsigned char red = colour.Red ();
1443 unsigned char blue = colour.Blue ();
1444 unsigned char green = colour.Green ();
1445 // white
1446 if((red == wp && blue == wp && green == wp) ||
1447 // not black and roundToWhite was specified
1448 ((red != 0 || blue != 0 || green != 0) && roundToWhite))
1449 {
1450 curCol = *wxWHITE;
1451 pixel = (int)WhitePixel((Display*) m_display,
1452 DefaultScreen((Display*) m_display));
1453 curCol.SetPixel(pixel);
1454 colour.SetPixel(pixel);
1455 }
1456 else
1457 {
1458 curCol = *wxBLACK;
1459 pixel = (int)BlackPixel((Display*) m_display,
1460 DefaultScreen((Display*) m_display));
1461 curCol.SetPixel(pixel);
1462 colour.SetPixel(pixel);
1463 }
1464 }
1465 else
1466 {
1467 curCol = colour;
1468 pixel = colour.AllocColour((Display*) m_display);
1469 curCol.SetPixel(pixel);
1470 }
1471
1472 return pixel;
1473}
1474
dfc54541 1475void wxWindowDC::SetPen( const wxPen &pen )
4bb6408c 1476{
af0bb3b1
VZ
1477 wxCHECK_RET( Ok(), "invalid dc" );
1478
2d120f83
JS
1479 m_pen = pen;
1480 if (!m_pen.Ok())
1481 return;
af0bb3b1 1482
2d120f83
JS
1483 wxBitmap oldStipple = m_currentStipple;
1484 int oldStyle = m_currentStyle;
1485 int oldFill = m_currentFill;
1486 int old_pen_width = m_currentPenWidth;
1487 int old_pen_join = m_currentPenJoin;
1488 int old_pen_cap = m_currentPenCap;
1489 int old_pen_nb_dash = m_currentPenDashCount;
69c44812 1490 wxX11Dash *old_pen_dash = m_currentPenDash;
af0bb3b1 1491
2d120f83
JS
1492 wxColour oldPenColour = m_currentColour;
1493 m_currentColour = m_pen.GetColour ();
1494 m_currentStyle = m_pen.GetStyle ();
1495 m_currentFill = m_pen.GetStyle (); // TODO?
1496 m_currentPenWidth = m_pen.GetWidth ();
1497 m_currentPenJoin = m_pen.GetJoin ();
1498 m_currentPenCap = m_pen.GetCap ();
1499 m_currentPenDashCount = m_pen.GetDashCount();
69c44812 1500 m_currentPenDash = (wxX11Dash*)m_pen.GetDash();
af0bb3b1 1501
2d120f83
JS
1502 if (m_currentStyle == wxSTIPPLE)
1503 m_currentStipple = * m_pen.GetStipple ();
af0bb3b1 1504
2d120f83
JS
1505 bool sameStyle = (oldStyle == m_currentStyle &&
1506 oldFill == m_currentFill &&
1507 old_pen_join == m_currentPenJoin &&
1508 old_pen_cap == m_currentPenCap &&
1509 old_pen_nb_dash == m_currentPenDashCount &&
1510 old_pen_dash == m_currentPenDash &&
1511 old_pen_width == m_currentPenWidth);
af0bb3b1 1512
2d120f83
JS
1513 bool sameColour = (oldPenColour.Ok () &&
1514 (oldPenColour.Red () == m_currentColour.Red ()) &&
1515 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1516 (oldPenColour.Green () == m_currentColour.Green ()) &&
1517 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1518
ea76a6a5 1519 if (!sameStyle || !GET_OPTIMIZATION)
16c1f7f3 1520 {
2d120f83
JS
1521 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1522 if (scaled_width < 0)
1523 scaled_width = 0;
af0bb3b1 1524
2d120f83
JS
1525 int style;
1526 int join;
1527 int cap;
69c44812
MB
1528 static const wxX11Dash dotted[] = {2, 5};
1529 static const wxX11Dash short_dashed[] = {4, 4};
1530 static const wxX11Dash long_dashed[] = {4, 8};
1531 static const wxX11Dash dotted_dashed[] = {6, 6, 2, 6};
af0bb3b1 1532
2d120f83
JS
1533 // We express dash pattern in pen width unit, so we are
1534 // independent of zoom factor and so on...
1535 int req_nb_dash;
69c44812 1536 const wxX11Dash *req_dash;
af0bb3b1 1537
2d120f83
JS
1538 switch (m_pen.GetStyle ())
1539 {
16c1f7f3 1540 case wxUSER_DASH:
2d120f83
JS
1541 req_nb_dash = m_currentPenDashCount;
1542 req_dash = m_currentPenDash;
1543 style = LineOnOffDash;
1544 break;
16c1f7f3 1545 case wxDOT:
2d120f83
JS
1546 req_nb_dash = 2;
1547 req_dash = dotted;
1548 style = LineOnOffDash;
1549 break;
16c1f7f3 1550 case wxSHORT_DASH:
2d120f83
JS
1551 req_nb_dash = 2;
1552 req_dash = short_dashed;
1553 style = LineOnOffDash;
1554 break;
16c1f7f3 1555 case wxLONG_DASH:
2d120f83
JS
1556 req_nb_dash = 2;
1557 req_dash = long_dashed;
1558 style = LineOnOffDash;
1559 break;
16c1f7f3 1560 case wxDOT_DASH:
2d120f83
JS
1561 req_nb_dash = 4;
1562 req_dash = dotted_dashed;
1563 style = LineOnOffDash;
1564 break;
16c1f7f3
JS
1565 case wxSTIPPLE:
1566 case wxSOLID:
1567 case wxTRANSPARENT:
1568 default:
2d120f83 1569 style = LineSolid;
69c44812 1570 req_dash = (wxX11Dash*)NULL;
2d120f83 1571 req_nb_dash = 0;
16c1f7f3 1572 }
af0bb3b1 1573
2d120f83 1574 if (req_dash && req_nb_dash)
16c1f7f3 1575 {
69c44812 1576 wxX11Dash *real_req_dash = new wxX11Dash[req_nb_dash];
2d120f83
JS
1577 if (real_req_dash)
1578 {
1579 int factor = scaled_width == 0 ? 1 : scaled_width;
1580 for (int i = 0; i < req_nb_dash; i++)
1581 real_req_dash[i] = req_dash[i] * factor;
1582 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
af0bb3b1 1583
2d120f83
JS
1584 if (m_window && m_window->GetBackingPixmap())
1585 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1586 delete[]real_req_dash;
1587 }
1588 else
1589 {
1590 // No Memory. We use non-scaled dash pattern...
1591 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
af0bb3b1 1592
2d120f83
JS
1593 if (m_window && m_window->GetBackingPixmap())
1594 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1595 }
16c1f7f3 1596 }
af0bb3b1 1597
2d120f83
JS
1598 switch (m_pen.GetCap ())
1599 {
16c1f7f3 1600 case wxCAP_PROJECTING:
2d120f83
JS
1601 cap = CapProjecting;
1602 break;
16c1f7f3 1603 case wxCAP_BUTT:
2d120f83
JS
1604 cap = CapButt;
1605 break;
16c1f7f3
JS
1606 case wxCAP_ROUND:
1607 default:
2d120f83
JS
1608 cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1609 break;
1610 }
af0bb3b1 1611
2d120f83
JS
1612 switch (m_pen.GetJoin ())
1613 {
16c1f7f3 1614 case wxJOIN_BEVEL:
2d120f83
JS
1615 join = JoinBevel;
1616 break;
16c1f7f3 1617 case wxJOIN_MITER:
2d120f83
JS
1618 join = JoinMiter;
1619 break;
16c1f7f3
JS
1620 case wxJOIN_ROUND:
1621 default:
2d120f83
JS
1622 join = JoinRound;
1623 break;
1624 }
af0bb3b1 1625
2d120f83 1626 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
af0bb3b1 1627
2d120f83
JS
1628 if (m_window && m_window->GetBackingPixmap())
1629 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
16c1f7f3 1630 }
af0bb3b1 1631
ea76a6a5 1632 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION))
16c1f7f3 1633 {
2d120f83 1634 Pixmap myStipple;
af0bb3b1 1635
2d120f83 1636 oldStipple = wxNullBitmap; // For later reset!!
af0bb3b1 1637
2d120f83
JS
1638 switch (m_currentFill)
1639 {
16c1f7f3 1640 case wxBDIAGONAL_HATCH:
2d120f83
JS
1641 if (bdiag == (Pixmap) 0)
1642 bdiag = XCreateBitmapFromData ((Display*) m_display,
1643 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1644 bdiag_bits, bdiag_width, bdiag_height);
1645 myStipple = bdiag;
1646 break;
16c1f7f3 1647 case wxFDIAGONAL_HATCH:
2d120f83
JS
1648 if (fdiag == (Pixmap) 0)
1649 fdiag = XCreateBitmapFromData ((Display*) m_display,
1650 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1651 fdiag_bits, fdiag_width, fdiag_height);
1652 myStipple = fdiag;
1653 break;
16c1f7f3 1654 case wxCROSS_HATCH:
2d120f83
JS
1655 if (cross == (Pixmap) 0)
1656 cross = XCreateBitmapFromData ((Display*) m_display,
1657 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1658 cross_bits, cross_width, cross_height);
1659 myStipple = cross;
1660 break;
16c1f7f3 1661 case wxHORIZONTAL_HATCH:
2d120f83
JS
1662 if (horiz == (Pixmap) 0)
1663 horiz = XCreateBitmapFromData ((Display*) m_display,
1664 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1665 horiz_bits, horiz_width, horiz_height);
1666 myStipple = horiz;
1667 break;
16c1f7f3 1668 case wxVERTICAL_HATCH:
2d120f83
JS
1669 if (verti == (Pixmap) 0)
1670 verti = XCreateBitmapFromData ((Display*) m_display,
1671 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1672 verti_bits, verti_width, verti_height);
1673 myStipple = verti;
1674 break;
16c1f7f3
JS
1675 case wxCROSSDIAG_HATCH:
1676 default:
2d120f83
JS
1677 if (cdiag == (Pixmap) 0)
1678 cdiag = XCreateBitmapFromData ((Display*) m_display,
1679 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1680 cdiag_bits, cdiag_width, cdiag_height);
1681 myStipple = cdiag;
1682 break;
1683 }
1684 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
af0bb3b1 1685
2d120f83
JS
1686 if (m_window && m_window->GetBackingPixmap())
1687 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
16c1f7f3
JS
1688 }
1689 else if (m_currentStipple.Ok()
ea76a6a5 1690 && ((m_currentStipple != oldStipple) || !GET_OPTIMIZATION))
16c1f7f3 1691 {
aae0472b 1692 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetDrawable());
af0bb3b1 1693
2d120f83 1694 if (m_window && m_window->GetBackingPixmap())
aae0472b 1695 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetDrawable());
16c1f7f3 1696 }
af0bb3b1 1697
ea76a6a5 1698 if ((m_currentFill != oldFill) || !GET_OPTIMIZATION)
16c1f7f3 1699 {
2d120f83 1700 int fill_style;
af0bb3b1 1701
2d120f83
JS
1702 if (m_currentFill == wxSTIPPLE)
1703 fill_style = FillStippled;
1704 else if (IS_HATCH (m_currentFill))
1705 fill_style = FillStippled;
1706 else
1707 fill_style = FillSolid;
1708 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1709 if (m_window && m_window->GetBackingPixmap())
1710 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
16c1f7f3 1711 }
af0bb3b1 1712
16c1f7f3 1713 // must test m_logicalFunction, because it involves background!
ea76a6a5 1714 if (!sameColour || !GET_OPTIMIZATION
2d120f83 1715 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
16c1f7f3 1716 {
2d120f83
JS
1717 int pixel = -1;
1718 if (m_pen.GetStyle () == wxTRANSPARENT)
1719 pixel = m_backgroundPixel;
16c1f7f3
JS
1720 else
1721 {
ab9d0a8c 1722 pixel = CalculatePixel(m_pen.GetColour(), m_currentColour, false);
16c1f7f3 1723 }
af0bb3b1 1724
2d120f83
JS
1725 // Finally, set the GC to the required colour
1726 if (pixel > -1)
395539f9 1727 SetForegroundPixelWithLogicalFunction(pixel);
16c1f7f3 1728 }
2d120f83
JS
1729 else
1730 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
af0bb3b1 1731
2d120f83 1732 m_autoSetting = 0;
af0bb3b1 1733}
4bb6408c 1734
dfc54541 1735void wxWindowDC::SetBrush( const wxBrush &brush )
4bb6408c 1736{
af0bb3b1
VZ
1737 wxCHECK_RET( Ok(), "invalid dc" );
1738
2d120f83 1739 m_brush = brush;
af0bb3b1 1740
2d120f83
JS
1741 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1742 return;
af0bb3b1 1743
2d120f83
JS
1744 int oldFill = m_currentFill;
1745 wxBitmap oldStipple = m_currentStipple;
af0bb3b1 1746
2d120f83 1747 m_autoSetting |= 0x1;
af0bb3b1 1748
2d120f83
JS
1749 m_currentFill = m_brush.GetStyle ();
1750 if (m_currentFill == wxSTIPPLE)
1751 m_currentStipple = * m_brush.GetStipple ();
af0bb3b1 1752
2d120f83
JS
1753 wxColour oldBrushColour(m_currentColour);
1754 m_currentColour = m_brush.GetColour ();
af0bb3b1 1755
2d120f83
JS
1756 bool sameColour = (oldBrushColour.Ok () &&
1757 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1758 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1759 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1760 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1761
2b830c41
MB
1762 int stippleDepth = -1;
1763
ea76a6a5 1764 if ((oldFill != m_brush.GetStyle ()) || !GET_OPTIMIZATION)
2d120f83
JS
1765 {
1766 switch (brush.GetStyle ())
1767 {
16c1f7f3 1768 case wxTRANSPARENT:
2d120f83 1769 break;
2b830c41
MB
1770 case wxSTIPPLE:
1771 stippleDepth = m_currentStipple.GetDepth();
1772 // fall through!
16c1f7f3
JS
1773 case wxBDIAGONAL_HATCH:
1774 case wxCROSSDIAG_HATCH:
1775 case wxFDIAGONAL_HATCH:
1776 case wxCROSS_HATCH:
1777 case wxHORIZONTAL_HATCH:
1778 case wxVERTICAL_HATCH:
2d120f83 1779 {
2b830c41
MB
1780 if (stippleDepth == -1) stippleDepth = 1;
1781
1782 // Chris Breeze 23/07/97: use background mode to
1783 // determine whether fill style should be solid or
1784 // transparent
1785 int style = stippleDepth == 1 ?
ab9d0a8c 1786 (m_backgroundMode == wxSOLID ?
2b830c41
MB
1787 FillOpaqueStippled : FillStippled) :
1788 FillTiled;
2d120f83
JS
1789 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1790 if (m_window && m_window->GetBackingPixmap())
1791 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1792 }
1793 break;
16c1f7f3
JS
1794 case wxSOLID:
1795 default:
2d120f83
JS
1796 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1797 if (m_window && m_window->GetBackingPixmap())
2b830c41
MB
1798 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking,
1799 FillSolid);
2d120f83
JS
1800 }
1801 }
af0bb3b1 1802
ea76a6a5 1803 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION))
16c1f7f3 1804 {
2d120f83 1805 Pixmap myStipple;
af0bb3b1 1806
2d120f83
JS
1807 switch (m_currentFill)
1808 {
16c1f7f3 1809 case wxBDIAGONAL_HATCH:
2d120f83
JS
1810 if (bdiag == (Pixmap) 0)
1811 bdiag = XCreateBitmapFromData ((Display*) m_display,
1812 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1813 bdiag_bits, bdiag_width, bdiag_height);
1814 myStipple = bdiag;
1815 break;
16c1f7f3 1816 case wxFDIAGONAL_HATCH:
2d120f83
JS
1817 if (fdiag == (Pixmap) 0)
1818 fdiag = XCreateBitmapFromData ((Display*) m_display,
1819 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1820 fdiag_bits, fdiag_width, fdiag_height);
1821 myStipple = fdiag;
1822 break;
16c1f7f3 1823 case wxCROSS_HATCH:
2d120f83
JS
1824 if (cross == (Pixmap) 0)
1825 cross = XCreateBitmapFromData ((Display*) m_display,
1826 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1827 cross_bits, cross_width, cross_height);
1828 myStipple = cross;
1829 break;
16c1f7f3 1830 case wxHORIZONTAL_HATCH:
2d120f83
JS
1831 if (horiz == (Pixmap) 0)
1832 horiz = XCreateBitmapFromData ((Display*) m_display,
1833 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1834 horiz_bits, horiz_width, horiz_height);
1835 myStipple = horiz;
1836 break;
16c1f7f3 1837 case wxVERTICAL_HATCH:
2d120f83
JS
1838 if (verti == (Pixmap) 0)
1839 verti = XCreateBitmapFromData ((Display*) m_display,
1840 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1841 verti_bits, verti_width, verti_height);
1842 myStipple = verti;
1843 break;
16c1f7f3
JS
1844 case wxCROSSDIAG_HATCH:
1845 default:
2d120f83
JS
1846 if (cdiag == (Pixmap) 0)
1847 cdiag = XCreateBitmapFromData ((Display*) m_display,
1848 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1849 cdiag_bits, cdiag_width, cdiag_height);
1850 myStipple = cdiag;
1851 break;
1852 }
1853 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
af0bb3b1 1854
2d120f83
JS
1855 if (m_window && m_window->GetBackingPixmap())
1856 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
16c1f7f3
JS
1857 }
1858 // X can forget the stipple value when resizing a window (apparently)
1859 // so always set the stipple.
2b830c41
MB
1860 else if (m_currentFill != wxSOLID && m_currentFill != wxTRANSPARENT &&
1861 m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
16c1f7f3 1862 {
2b830c41
MB
1863 if (m_currentStipple.GetDepth() == 1)
1864 {
1865 XSetStipple ((Display*) m_display, (GC) m_gc,
aae0472b 1866 (Pixmap) m_currentStipple.GetDrawable());
2d120f83 1867 if (m_window && m_window->GetBackingPixmap())
2b830c41 1868 XSetStipple ((Display*) m_display,(GC) m_gcBacking,
aae0472b 1869 (Pixmap) m_currentStipple.GetDrawable());
2b830c41
MB
1870 }
1871 else
1872 {
1873 XSetTile ((Display*) m_display, (GC) m_gc,
aae0472b 1874 (Pixmap) m_currentStipple.GetDrawable());
2b830c41
MB
1875 if (m_window && m_window->GetBackingPixmap())
1876 XSetTile ((Display*) m_display,(GC) m_gcBacking,
aae0472b 1877 (Pixmap) m_currentStipple.GetDrawable());
2b830c41 1878 }
16c1f7f3 1879 }
af0bb3b1 1880
16c1f7f3 1881 // must test m_logicalFunction, because it involves background!
ea76a6a5 1882 if (!sameColour || !GET_OPTIMIZATION || m_logicalFunction == wxXOR)
16c1f7f3 1883 {
ab9d0a8c
WS
1884 int pixel = CalculatePixel(m_brush.GetColour(), m_currentColour, true);
1885
2d120f83 1886 if (pixel > -1)
395539f9 1887 SetForegroundPixelWithLogicalFunction(pixel);
16c1f7f3 1888 }
2d120f83
JS
1889 else
1890 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
af0bb3b1 1891}
4bb6408c 1892
dfc54541 1893void wxWindowDC::SetBackground( const wxBrush &brush )
4bb6408c 1894{
af0bb3b1
VZ
1895 wxCHECK_RET( Ok(), "invalid dc" );
1896
2d120f83 1897 m_backgroundBrush = brush;
af0bb3b1 1898
2d120f83
JS
1899 if (!m_backgroundBrush.Ok())
1900 return;
af0bb3b1 1901
395539f9 1902 m_backgroundPixel = m_backgroundBrush.GetColour().AllocColour(m_display);
a91b47e8 1903
2d120f83
JS
1904 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1905 // And Blit,... (Any fct that use XCopyPlane, in fact.)
395539f9 1906 XSetBackground ((Display*) m_display, (GC) m_gc, m_backgroundPixel);
2d120f83 1907 if (m_window && m_window->GetBackingPixmap())
395539f9
MB
1908 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1909 m_backgroundPixel);
af0bb3b1 1910}
4bb6408c 1911
dfc54541 1912void wxWindowDC::SetLogicalFunction( int function )
4bb6408c 1913{
af0bb3b1
VZ
1914 wxCHECK_RET( Ok(), "invalid dc" );
1915
2d120f83 1916 int x_function;
af0bb3b1 1917
2d120f83
JS
1918 /* MATTHEW: [9] */
1919 if (m_logicalFunction == function)
1920 return;
af0bb3b1 1921
2d120f83 1922 switch (function)
16c1f7f3
JS
1923 {
1924 case wxCLEAR:
2d120f83
JS
1925 x_function = GXclear;
1926 break;
16c1f7f3 1927 case wxXOR:
2d120f83
JS
1928 x_function = GXxor;
1929 break;
16c1f7f3 1930 case wxINVERT:
2d120f83
JS
1931 x_function = GXinvert;
1932 break;
16c1f7f3 1933 case wxOR_REVERSE:
2d120f83
JS
1934 x_function = GXorReverse;
1935 break;
16c1f7f3 1936 case wxAND_REVERSE:
2d120f83
JS
1937 x_function = GXandReverse;
1938 break;
16c1f7f3 1939 case wxAND:
2d120f83
JS
1940 x_function = GXand;
1941 break;
16c1f7f3 1942 case wxOR:
2d120f83
JS
1943 x_function = GXor;
1944 break;
16c1f7f3 1945 case wxAND_INVERT:
2d120f83
JS
1946 x_function = GXandInverted;
1947 break;
16c1f7f3 1948 case wxNO_OP:
2d120f83
JS
1949 x_function = GXnoop;
1950 break;
16c1f7f3 1951 case wxNOR:
2d120f83
JS
1952 x_function = GXnor;
1953 break;
16c1f7f3 1954 case wxEQUIV:
2d120f83
JS
1955 x_function = GXequiv;
1956 break;
16c1f7f3 1957 case wxSRC_INVERT:
2d120f83
JS
1958 x_function = GXcopyInverted;
1959 break;
16c1f7f3 1960 case wxOR_INVERT:
2d120f83
JS
1961 x_function = GXorInverted;
1962 break;
16c1f7f3 1963 case wxNAND:
2d120f83
JS
1964 x_function = GXnand;
1965 break;
16c1f7f3 1966 case wxSET:
2d120f83
JS
1967 x_function = GXset;
1968 break;
16c1f7f3
JS
1969 case wxCOPY:
1970 default:
2d120f83
JS
1971 x_function = GXcopy;
1972 break;
16c1f7f3 1973 }
af0bb3b1 1974
2d120f83
JS
1975 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
1976 if (m_window && m_window->GetBackingPixmap())
1977 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
af0bb3b1 1978
2d120f83
JS
1979 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
1980 /* MATTHEW: [9] Need to redo pen simply */
1981 m_autoSetting |= 0x2;
af0bb3b1 1982
2d120f83 1983 m_logicalFunction = function;
af0bb3b1
VZ
1984
1985}
4bb6408c 1986
dfc54541 1987void wxWindowDC::SetTextForeground( const wxColour &col )
4bb6408c 1988{
af0bb3b1
VZ
1989 wxCHECK_RET( Ok(), "invalid dc" );
1990
2d120f83 1991 m_textForegroundColour = col;
af0bb3b1 1992}
4bb6408c 1993
dfc54541 1994void wxWindowDC::SetTextBackground( const wxColour &col )
4bb6408c 1995{
af0bb3b1
VZ
1996 wxCHECK_RET( Ok(), "invalid dc" );
1997
2d120f83 1998 m_textBackgroundColour = col;
af0bb3b1 1999}
4bb6408c 2000
dfc54541 2001void wxWindowDC::SetBackgroundMode( int mode )
4bb6408c 2002{
2d120f83 2003 m_backgroundMode = mode;
af0bb3b1 2004}
16c1f7f3
JS
2005
2006void wxWindowDC::SetPalette( const wxPalette& palette )
2007{
2d120f83
JS
2008 if (m_window)
2009 {
2010 if (palette.Ok())
2011 /* Use GetXColormap */
2012 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2013 (Colormap) palette.GetXColormap());
2014 else
2015 /* Use wxGetMainColormap */
2016 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2017 (Colormap) wxTheApp->GetMainColormap(m_display));
2018 }
af0bb3b1 2019}
4bb6408c 2020
148b44a1 2021static void wxCopyRegion( WXRegion src, WXRegion& dst )
4bb6408c 2022{
148b44a1
MB
2023 if( !dst )
2024 dst = XCreateRegion();
2025 XUnionRegion( (Region)src, (Region)src, (Region)dst );
2026}
af0bb3b1 2027
148b44a1
MB
2028// Helper function; userRegion is the region set by calling SetClippingRegion
2029void wxWindowDC::SetDCClipping( WXRegion userRegion )
2030{
2031 bool hasUpdateRegion = m_window && m_window->GetUpdateRegion().Ok();
2032 // this means that we should start the clip region from scratch,
2033 // or from the update region, if any
2034 if( !userRegion )
16c1f7f3 2035 {
148b44a1
MB
2036 if( m_clipRegion )
2037 XDestroyRegion( (Region)m_clipRegion );
2038 m_clipRegion = (WXRegion)NULL;
2039
2040 if( hasUpdateRegion )
2041 wxCopyRegion( m_window->GetUpdateRegion().GetX11Region(),
2042 m_clipRegion );
16c1f7f3 2043 }
148b44a1
MB
2044 // intersect the user region, if any, with the
2045 // exisiting clip region
2046 else // if( userRegion )
16c1f7f3 2047 {
148b44a1
MB
2048 if( !m_clipRegion )
2049 wxCopyRegion( userRegion, m_clipRegion );
2050 else
2051 XIntersectRegion( (Region)m_clipRegion,
2052 (Region)userRegion, (Region)m_clipRegion );
16c1f7f3 2053 }
af0bb3b1 2054
148b44a1
MB
2055 if( m_clipRegion )
2056 XSetRegion( (Display*)m_display, (GC)m_gc, (Region)m_clipRegion );
2057 else
2058 XSetClipMask( (Display*)m_display, (GC)m_gc, None );
16c1f7f3 2059}
4bb6408c 2060
148b44a1
MB
2061void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y,
2062 wxCoord width, wxCoord height )
4bb6408c 2063{
33caefb3 2064 wxDC::DoSetClippingRegion( x, y, width, height );
af0bb3b1 2065
148b44a1 2066 wxRegion temp(x, y, width, height);
af0bb3b1 2067
148b44a1 2068 SetDCClipping(temp.GetX11Region());
af0bb3b1 2069
2d120f83
JS
2070 // Needs to work differently for Pixmap: without this,
2071 // there's a nasty (Display*) m_display bug. 8/12/94
2072 if (m_window && m_window->GetBackingPixmap())
2073 {
2074 XRectangle rects[1];
af0bb3b1 2075 rects[0].x = XLOG2DEV_2(x);
2d120f83
JS
2076 rects[0].y = YLOG2DEV_2(y);
2077 rects[0].width = XLOG2DEVREL(width);
2078 rects[0].height = YLOG2DEVREL(height);
148b44a1
MB
2079 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking,
2080 0, 0, rects, 1, Unsorted);
2d120f83 2081 }
af0bb3b1 2082}
4bb6408c 2083
af0bb3b1 2084void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
a724d789 2085{
2d120f83 2086 wxRect box = region.GetBox();
af0bb3b1 2087
33caefb3 2088 wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height );
af0bb3b1 2089
148b44a1 2090 SetDCClipping(region.GetX11Region());
af0bb3b1 2091
2d120f83
JS
2092 // Needs to work differently for Pixmap: without this,
2093 // there's a nasty (Display*) m_display bug. 8/12/94
2094 if (m_window && m_window->GetBackingPixmap())
2095 {
2096 XRectangle rects[1];
2097 rects[0].x = XLOG2DEV_2(box.x);
2098 rects[0].y = YLOG2DEV_2(box.y);
2099 rects[0].width = XLOG2DEVREL(box.width);
2100 rects[0].height = YLOG2DEVREL(box.height);
148b44a1
MB
2101 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking,
2102 0, 0, rects, 1, Unsorted);
2d120f83 2103 }
af0bb3b1 2104}
a724d789
JS
2105
2106
af0bb3b1 2107void wxWindowDC::DestroyClippingRegion()
4bb6408c 2108{
2d120f83 2109 wxDC::DestroyClippingRegion();
af0bb3b1 2110
148b44a1 2111 SetDCClipping(NULL);
af0bb3b1 2112
2d120f83 2113 if (m_window && m_window->GetBackingPixmap())
148b44a1 2114 XSetClipMask ((Display*) m_display, (GC) m_gcBacking, None);
4bb6408c
JS
2115}
2116
af0bb3b1
VZ
2117// Resolution in pixels per logical inch
2118wxSize wxWindowDC::GetPPI() const
4bb6408c 2119{
148b44a1 2120 // TODO
af0bb3b1 2121 return wxSize(100, 100);
4bb6408c
JS
2122}
2123
af0bb3b1 2124int wxWindowDC::GetDepth() const
7bcb11d3 2125{
af0bb3b1
VZ
2126 // TODO
2127 return 24;
7bcb11d3
JS
2128}
2129
96f201da
RR
2130
2131
2132
af0bb3b1
VZ
2133// ----------------------------------------------------------------------------
2134// wxPaintDC
2135// ----------------------------------------------------------------------------
55acd85e 2136
af0bb3b1 2137wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win)
55acd85e 2138{
148b44a1 2139 // Set the clipping region.to the update region
ab9d0a8c 2140 SetDCClipping((WXRegion)NULL);
55acd85e
JS
2141}
2142
2143wxPaintDC::~wxPaintDC()
2144{
55acd85e 2145 if (m_window)
af0bb3b1 2146 m_window->ClearUpdateRegion();
148b44a1 2147 SetDCClipping((WXRegion)NULL);
af0bb3b1
VZ
2148}
2149
2150// ----------------------------------------------------------------------------
2151// private functions
2152// ----------------------------------------------------------------------------
2153
2154/*
2155 Used when copying between drawables on different (Display*) m_displays. Not
2156 very fast, but better than giving up.
2157*/
2158
2159static void XCopyRemote(Display *src_display, Display *dest_display,
2160 Drawable src, Drawable dest,
2161 GC destgc,
2162 int srcx, int srcy,
2163 unsigned int w, unsigned int h,
2164 int destx, int desty,
2165 bool more, XImage **cache)
2166{
2167 XImage *image, *destimage;
2168 Colormap destcm, srccm;
2169 static const int CACHE_SIZE = 256;
2170
2171 unsigned int i, j;
2172 unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2173 int k, cache_pos, all_cache;
2174
2175 if (!cache || !*cache)
2176 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2177 else
2178 image = *cache;
2179
2180 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2181
2182 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2183 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2184
2185 cache_pos = 0;
96be256b 2186 all_cache = False;
af0bb3b1
VZ
2187
2188 for (i = 0; i < w; i++)
2189 for (j = 0; j < h; j++) {
2190 unsigned long pixel;
2191 XColor xcol;
2192
2193 pixel = XGetPixel(image, i, j);
2194 for (k = cache_pos; k--; )
2195 if (cachesrc[k] == pixel) {
2196 pixel = cachedest[k];
2197 goto install;
2198 }
2199 if (all_cache)
2200 for (k = CACHE_SIZE; k-- > cache_pos; )
2201 if (cachesrc[k] == pixel) {
2202 pixel = cachedest[k];
2203 goto install;
2204 }
2205
2206 cachesrc[cache_pos] = xcol.pixel = pixel;
2207 XQueryColor(src_display, srccm, &xcol);
2208 if (!XAllocColor(dest_display, destcm, &xcol))
2209 xcol.pixel = 0;
2210 cachedest[cache_pos] = pixel = xcol.pixel;
2211
2212 if (++cache_pos >= CACHE_SIZE) {
2213 cache_pos = 0;
96be256b 2214 all_cache = true;
af0bb3b1
VZ
2215 }
2216
2217install:
2218 XPutPixel(destimage, i, j, pixel);
2219 }
2220
2221 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2222 XDestroyImage(destimage);
2223
2224 if (more)
2225 *cache = image;
2226 else
2227 XDestroyImage(image);
2228}
2229
2230#if 0
2231
2232/* Helper function for 16-bit fonts */
2233static int str16len(const char *s)
2234{
2235 int count = 0;
2236
2237 while (s[0] && s[1]) {
2238 count++;
2239 s += 2;
2240 }
2241
2242 return count;
55acd85e
JS
2243}
2244
af0bb3b1 2245#endif // 0