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