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