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