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