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