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