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