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