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