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