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