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