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