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