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