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