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