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