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