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