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