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