]> git.saurik.com Git - wxWidgets.git/blame - src/motif/dcclient.cpp
wxDC::SetFont can now handle invalid font and doesn't assert anymore (other ports...
[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 873bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
0cbff120
JS
874 wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
875 wxCoord xsrcMask, wxCoord ysrcMask )
2d120f83 876{
af0bb3b1
VZ
877 wxCHECK_MSG( Ok(), FALSE, "invalid dc" );
878
879 wxWindowDC* sourceDC = wxDynamicCast(source, wxWindowDC);
880
881 wxASSERT_MSG( sourceDC, "Blit source DC must be wxWindowDC or derived class." );
882
2d120f83 883 // FreeGetPixelCache();
af0bb3b1
VZ
884
885 // Be sure that foreground pixels (1) of the Icon will be painted with pen
886 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
2d120f83
JS
887 // last selected background color. [::SetBackground]
888 if (m_pen.Ok() && m_autoSetting)
889 SetPen (m_pen);
a91b47e8
JS
890
891 // Do bitmap scaling if necessary
892
893 wxBitmap *scaledBitmap = (wxBitmap*) NULL;
894 Pixmap sourcePixmap = (Pixmap) NULL;
895 double scaleX, scaleY;
896 GetUserScale(& scaleX, & scaleY);
897
0cbff120
JS
898 /* TODO: use the mask origin when drawing transparently */
899 if (xsrcMask == -1 && ysrcMask == -1)
900 {
901 xsrcMask = xsrc; ysrcMask = ysrc;
902 }
903
a91b47e8
JS
904 // Sorry, can't scale masks just yet
905 if (!useMask && (scaleX != 1.0 || scaleY != 1.0) && sourceDC->IsKindOf(CLASSINFO(wxMemoryDC)))
906 {
907 wxMemoryDC* memDC = (wxMemoryDC*) sourceDC;
908 wxBitmap& bitmap = memDC->GetBitmap();
909
910 wxASSERT_MSG( (bitmap.Ok()), "Bad source bitmap in wxWindowDC::Blit");
911
912 wxImage image(bitmap);
913 if (!image.Ok())
914 {
915 sourcePixmap = (Pixmap) bitmap.GetPixmap();
916 }
917 else
918 {
919 int scaledW = (int) (bitmap.GetWidth() * scaleX);
920 int scaledH = (int) (bitmap.GetHeight() * scaleY);
af0bb3b1 921
a91b47e8
JS
922 image = image.Scale(scaledW, scaledH);
923 scaledBitmap = new wxBitmap(image.ConvertToBitmap());
924 sourcePixmap = (Pixmap) scaledBitmap->GetPixmap();
af0bb3b1 925 }
a91b47e8
JS
926 }
927 else
928 sourcePixmap = (Pixmap) sourceDC->m_pixmap;
929
930 if (m_pixmap && sourcePixmap)
2d120f83
JS
931 {
932 /* MATTHEW: [9] */
933 int orig = m_logicalFunction;
af0bb3b1 934
2d120f83 935 SetLogicalFunction (rop);
af0bb3b1 936
2d120f83
JS
937 if (m_display != sourceDC->m_display)
938 {
939 XImage *cache = NULL;
af0bb3b1 940
2d120f83
JS
941 if (m_window && m_window->GetBackingPixmap())
942 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display,
a91b47e8 943 (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),
2d120f83
JS
944 (GC) m_gcBacking,
945 source->LogicalToDeviceX (xsrc),
946 source->LogicalToDeviceY (ysrc),
947 source->LogicalToDeviceXRel(width),
948 source->LogicalToDeviceYRel(height),
949 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest),
950 TRUE, &cache);
af0bb3b1 951
2d120f83
JS
952 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
953 {
954 wxMemoryDC *memDC = (wxMemoryDC *)source;
955 wxBitmap& sel = memDC->GetBitmap();
956 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() )
957 {
958 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap());
959 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
960 }
961 }
af0bb3b1 962
a91b47e8 963 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
2d120f83
JS
964 source->LogicalToDeviceX (xsrc),
965 source->LogicalToDeviceY (ysrc),
966 source->LogicalToDeviceXRel(width),
967 source->LogicalToDeviceYRel(height),
968 XLOG2DEV (xdest), YLOG2DEV (ydest),
969 FALSE, &cache);
af0bb3b1 970
2d120f83
JS
971 if ( useMask )
972 {
973 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
974 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
975 }
af0bb3b1 976
2d120f83
JS
977 } else
978 {
979 if (m_window && m_window->GetBackingPixmap())
980 {
981 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
982 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetBitmap().GetDepth() == 1)
983 {
a91b47e8 984 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
2d120f83
JS
985 source->LogicalToDeviceX (xsrc),
986 source->LogicalToDeviceY (ysrc),
987 source->LogicalToDeviceXRel(width),
988 source->LogicalToDeviceYRel(height),
989 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1);
990 }
991 else
992 {
a91b47e8 993 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
2d120f83
JS
994 source->LogicalToDeviceX (xsrc),
995 source->LogicalToDeviceY (ysrc),
996 source->LogicalToDeviceXRel(width),
997 source->LogicalToDeviceYRel(height),
998 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest));
999 }
1000 }
1001 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
1002 {
1003 wxMemoryDC *memDC = (wxMemoryDC *)source;
1004 wxBitmap& sel = memDC->GetBitmap();
1005 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() )
1006 {
1007 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap());
1008 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
1009 }
1010 }
af0bb3b1 1011
2d120f83
JS
1012 // Check if we're copying from a mono bitmap
1013 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) &&
1014 ((wxMemoryDC*)source)->GetBitmap().Ok() && (((wxMemoryDC*)source)->GetBitmap().GetDepth () == 1))
1015 {
a91b47e8 1016 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
2d120f83
JS
1017 source->LogicalToDeviceX (xsrc),
1018 source->LogicalToDeviceY (ysrc),
1019 source->LogicalToDeviceXRel(width),
1020 source->LogicalToDeviceYRel(height),
1021 XLOG2DEV (xdest), YLOG2DEV (ydest), 1);
1022 }
1023 else
1024 {
a91b47e8 1025 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
2d120f83
JS
1026 source->LogicalToDeviceX (xsrc),
1027 source->LogicalToDeviceY (ysrc),
1028 source->LogicalToDeviceXRel(width),
1029 source->LogicalToDeviceYRel(height),
1030 XLOG2DEV (xdest), YLOG2DEV (ydest));
af0bb3b1 1031
2d120f83
JS
1032 }
1033 if ( useMask )
1034 {
1035 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
1036 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
1037 }
af0bb3b1 1038
2d120f83
JS
1039 } /* Remote/local (Display*) m_display */
1040 CalcBoundingBox (xdest, ydest);
1041 CalcBoundingBox (xdest + width, ydest + height);
af0bb3b1 1042
2d120f83 1043 SetLogicalFunction(orig);
a91b47e8
JS
1044
1045 if (scaledBitmap) delete scaledBitmap;
af0bb3b1 1046
2d120f83 1047 return TRUE;
16c1f7f3 1048 }
a91b47e8
JS
1049 if (scaledBitmap) delete scaledBitmap;
1050
16c1f7f3 1051 return FALSE;
16c1f7f3
JS
1052}
1053
7b65ea1a 1054void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
4bb6408c 1055{
af0bb3b1
VZ
1056 wxCHECK_RET( Ok(), "invalid dc" );
1057
1058 // Since X draws from the baseline of the text, must add the text height
2d120f83
JS
1059 int cx = 0;
1060 int cy = 0;
1061 int ascent = 0;
1062 int slen;
af0bb3b1
VZ
1063
1064 slen = strlen(text);
1065
2d120f83 1066 if (m_font.Ok())
16c1f7f3 1067 {
2d120f83
JS
1068 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1069 int direction, descent;
1070 XCharStruct overall_return;
af0bb3b1 1071#if 0
2d120f83
JS
1072 if (use16)
1073 (void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction,
1074 &ascent, &descent, &overall_return);
1075 else
af0bb3b1 1076#endif // 0
2d120f83 1077 (void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction,
af0bb3b1
VZ
1078 &ascent, &descent, &overall_return);
1079
2d120f83
JS
1080 cx = overall_return.width;
1081 cy = ascent + descent;
16c1f7f3 1082 }
af0bb3b1
VZ
1083
1084 // First draw a rectangle representing the text background, if a text
1085 // background is specified
2d120f83 1086 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
16c1f7f3 1087 {
2d120f83 1088 wxColour oldPenColour = m_currentColour;
16c1f7f3 1089 m_currentColour = m_textBackgroundColour;
2d120f83
JS
1090 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1091 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1092 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1093 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
af0bb3b1 1094
2d120f83
JS
1095 // This separation of the big && test required for gcc2.7/HP UX 9.02
1096 // or pixel value can be corrupted!
1097 sameColour = (sameColour &&
1098 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
af0bb3b1 1099
2d120f83 1100 if (!sameColour || !GetOptimization())
16c1f7f3 1101 {
2d120f83
JS
1102 int pixel = m_textBackgroundColour.AllocColour(m_display);
1103 m_currentColour = m_textBackgroundColour;
af0bb3b1 1104
2d120f83
JS
1105 // Set the GC to the required colour
1106 if (pixel > -1)
1107 {
1108 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1109 if (m_window && m_window->GetBackingPixmap())
1110 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1111 }
16c1f7f3 1112 }
2d120f83
JS
1113 else
1114 m_textBackgroundColour = oldPenColour ;
af0bb3b1 1115
2d120f83
JS
1116 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1117 if (m_window && m_window->GetBackingPixmap())
1118 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
16c1f7f3
JS
1119 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1120 }
af0bb3b1 1121
2d120f83
JS
1122 // Now set the text foreground and draw the text
1123 if (m_textForegroundColour.Ok ())
1124 {
1125 wxColour oldPenColour = m_currentColour;
1126 m_currentColour = m_textForegroundColour;
1127 bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () &&
1128 (oldPenColour.Red () == m_currentColour.Red ()) &&
1129 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1130 (oldPenColour.Green () == m_currentColour.Green ()) &&
1131 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1132
2d120f83 1133 if (!sameColour || !GetOptimization())
16c1f7f3 1134 {
2d120f83
JS
1135 int pixel = -1;
1136 if (!m_colour) // Mono display
1137 {
1138 // Unless foreground is really white, draw it in black
1139 unsigned char red = m_textForegroundColour.Red ();
1140 unsigned char blue = m_textForegroundColour.Blue ();
1141 unsigned char green = m_textForegroundColour.Green ();
1142 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1143 && green == (unsigned char) 255)
1144 {
1145 m_currentColour = *wxWHITE;
1146 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1147 m_currentColour.SetPixel(pixel);
1148 m_textForegroundColour.SetPixel(pixel);
1149 }
1150 else
1151 {
1152 m_currentColour = *wxBLACK;
1153 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1154 m_currentColour.SetPixel(pixel);
1155 m_textForegroundColour.SetPixel(pixel);
1156 }
1157 }
1158 else
1159 {
1160 pixel = m_textForegroundColour.AllocColour((Display*) m_display);
1161 m_currentColour.SetPixel(pixel);
1162 }
af0bb3b1 1163
2d120f83
JS
1164 // Set the GC to the required colour
1165 if (pixel > -1)
1166 {
1167 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1168 if (m_window && m_window->GetBackingPixmap())
1169 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1170 }
16c1f7f3
JS
1171 }
1172 else
2d120f83
JS
1173 m_textForegroundColour = oldPenColour;
1174 }
af0bb3b1
VZ
1175
1176 // We need to add the ascent, not the whole height, since X draws at the
1177 // point above the descender.
1178#if 0
16c1f7f3 1179 if (use16)
af0bb3b1 1180 XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
2d120f83
JS
1181 (XChar2b *)(char*) (const char*) text, slen);
1182 else
af0bb3b1
VZ
1183#endif // 0
1184 XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1185
2d120f83 1186 if (m_window && m_window->GetBackingPixmap()) {
af0bb3b1 1187#if 0
2d120f83
JS
1188 if (use16)
1189 XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
16c1f7f3
JS
1190 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1191 (XChar2b *)(char*) (const char*) text, slen);
2d120f83 1192 else
af0bb3b1 1193#endif // 0
2d120f83
JS
1194 XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1195 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, (char*) (const char*) text, slen);
1196 }
af0bb3b1 1197
7b65ea1a 1198 wxCoord w, h;
2d120f83
JS
1199 GetTextExtent (text, &w, &h);
1200 CalcBoundingBox (x + w, y + h);
1201 CalcBoundingBox (x, y);
af0bb3b1 1202}
4bb6408c 1203
95724b1a
VZ
1204void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
1205{
1206 if (angle == 0.0)
1207 {
1208 DrawText(text, x, y);
1209 return;
1210 }
1211
1212 wxCHECK_RET( Ok(), "invalid dc" );
1213
1214 // Since X draws from the baseline of the text, must add the text height
1215 int cx = 0;
1216 int cy = 0;
1217 int ascent = 0;
1218 int slen;
1219
1220 slen = strlen(text);
1221
1222 if (m_font.Ok())
1223 {
1224 // Calculate text extent.
1225 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1226 int direction, descent;
1227 XCharStruct overall_return;
1228#if 0
1229 if (use16)
1230 (void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction,
1231 &ascent, &descent, &overall_return);
1232 else
1233#endif // 0
1234 (void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction,
1235 &ascent, &descent, &overall_return);
1236
1237 cx = overall_return.width;
1238 cy = ascent + descent;
1239 }
1240
1241 wxBitmap src(cx, cy);
1242 wxMemoryDC dc;
1243 dc.SelectObject(src);
1244 dc.SetFont(GetFont());
1245 dc.SetBackground(*wxWHITE_BRUSH);
1246 dc.SetBrush(*wxBLACK_BRUSH);
1247 dc.Clear();
1248 dc.DrawText(text, 0, 0);
1249 dc.SetFont(wxNullFont);
1250
1251 // Calculate the size of the rotated bounding box.
1252 double dx = cos(angle / 180.0 * M_PI);
1253 double dy = sin(angle / 180.0 * M_PI);
1254 double x4 = -cy * dy;
1255 double y4 = cy * dx;
1256 double x3 = cx * dx;
1257 double y3 = cx * dy;
1258 double x2 = x3 + x4;
1259 double y2 = y3 + y4;
1260 double x1 = x;
1261 double y1 = y;
1262
1263 // Create image from the source bitmap after writing the text into it.
1264 wxImage image(src);
1265
1266 int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
1267 int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
1268 int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
1269 int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
1270
1271 // This rotates counterclockwise around the top left corner.
1272 for (int rx = minx; rx < maxx; rx++)
1273 {
1274 for (int ry = miny; ry < maxy; ry++)
1275 {
1276 // transform dest coords to source coords
1277 int sx = (int) (rx * dx + ry * dy + 0.5);
1278 int sy = (int) (ry * dx - rx * dy + 0.5);
1279 if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
1280 {
1281 // draw black pixels, ignore white ones (i.e. transparent b/g)
1282 if (image.GetRed(sx, sy) == 0)
95724b1a 1283 {
dc1efb1d 1284 DrawPoint((wxCoord) (x1 + maxx - rx), (wxCoord) (cy + y1 - ry));
95724b1a
VZ
1285 }
1286 else
1287 {
1288 // Background
1289 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1290 }
1291 }
1292 }
1293 }
1294
1295#if 0
1296 // First draw a rectangle representing the text background, if a text
1297 // background is specified
1298 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1299 {
1300 wxColour oldPenColour = m_currentColour;
1301 m_currentColour = m_textBackgroundColour;
1302 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1303 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1304 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1305 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1306
1307 // This separation of the big && test required for gcc2.7/HP UX 9.02
1308 // or pixel value can be corrupted!
1309 sameColour = (sameColour &&
1310 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1311
1312 if (!sameColour || !GetOptimization())
1313 {
1314 int pixel = m_textBackgroundColour.AllocColour(m_display);
1315 m_currentColour = m_textBackgroundColour;
1316
1317 // Set the GC to the required colour
1318 if (pixel > -1)
1319 {
1320 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1321 if (m_window && m_window->GetBackingPixmap())
1322 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1323 }
1324 }
1325 else
1326 m_textBackgroundColour = oldPenColour ;
1327
1328 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1329 if (m_window && m_window->GetBackingPixmap())
1330 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1331 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1332 }
1333#endif
1334
1335 long w, h;
1336 // XXX use pixmap size
1337 GetTextExtent (text, &w, &h);
1338 CalcBoundingBox (x + w, y + h);
1339 CalcBoundingBox (x, y);
1340}
1341
af0bb3b1 1342bool wxWindowDC::CanGetTextExtent() const
4bb6408c 1343{
2d120f83 1344 return TRUE;
af0bb3b1 1345}
4bb6408c 1346
7b65ea1a
MB
1347void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1348 wxCoord *descent, wxCoord *externalLeading,
af0bb3b1 1349 wxFont *font ) const
4bb6408c 1350{
af0bb3b1
VZ
1351 wxCHECK_RET( Ok(), "invalid dc" );
1352
2d120f83
JS
1353 wxFont* theFont = font;
1354 if (!theFont)
af0bb3b1
VZ
1355 theFont = (wxFont *)&m_font; // const_cast
1356
2d120f83
JS
1357 if (!theFont->Ok())
1358 {
1359 // TODO: this should be an error log function
1360 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
af0bb3b1 1361
33caefb3
RR
1362 if (width) *width = -1;
1363 if (height) *height = -1;
2d120f83
JS
1364 return;
1365 }
af0bb3b1 1366
2d120f83 1367 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
af0bb3b1 1368
2d120f83
JS
1369 int direction, ascent, descent2;
1370 XCharStruct overall;
1371 int slen;
af0bb3b1
VZ
1372
1373#if 0
1374 if (use16)
1375 slen = str16len(string);
1376 else
1377#endif // 0
1378 slen = strlen(string);
1379
1380#if 0
2d120f83
JS
1381 if (use16)
1382 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1383 &ascent, &descent2, &overall);
1384 else
af0bb3b1 1385#endif // 0
2d120f83
JS
1386 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1387 &ascent, &descent2, &overall);
af0bb3b1 1388
33caefb3
RR
1389 if (width) *width = XDEV2LOGREL (overall.width);
1390 if (height) *height = YDEV2LOGREL (ascent + descent2);
2d120f83
JS
1391 if (descent)
1392 *descent = descent2;
1393 if (externalLeading)
1394 *externalLeading = 0;
af0bb3b1 1395}
4bb6408c 1396
7b65ea1a 1397wxCoord wxWindowDC::GetCharWidth() const
4bb6408c 1398{
af0bb3b1
VZ
1399 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1400 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1401
2d120f83 1402 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
af0bb3b1 1403
2d120f83
JS
1404 int direction, ascent, descent;
1405 XCharStruct overall;
1406 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
16c1f7f3 1407 &descent, &overall);
2d120f83 1408 return XDEV2LOGREL(overall.width);
af0bb3b1 1409}
4bb6408c 1410
7b65ea1a 1411wxCoord wxWindowDC::GetCharHeight() const
4bb6408c 1412{
af0bb3b1
VZ
1413 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1414 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1415
2d120f83 1416 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
af0bb3b1 1417
2d120f83
JS
1418 int direction, ascent, descent;
1419 XCharStruct overall;
1420 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
16c1f7f3 1421 &descent, &overall);
2d120f83
JS
1422 // return XDEV2LOGREL(overall.ascent + overall.descent);
1423 return XDEV2LOGREL(ascent + descent);
af0bb3b1 1424}
4bb6408c 1425
af0bb3b1 1426void wxWindowDC::Clear()
4bb6408c 1427{
af0bb3b1
VZ
1428 wxCHECK_RET( Ok(), "invalid dc" );
1429
2d120f83
JS
1430 int w, h;
1431 if (m_window)
16c1f7f3 1432 {
2d120f83 1433 m_window->GetSize(&w, &h);
af0bb3b1 1434
2d120f83
JS
1435 if (m_window && m_window->GetBackingPixmap())
1436 {
1437 w = m_window->GetPixmapWidth();
1438 h = m_window->GetPixmapHeight();
1439 }
16c1f7f3 1440 }
2d120f83 1441 else
16c1f7f3
JS
1442 {
1443 if (this->IsKindOf(CLASSINFO(wxMemoryDC)))
1444 {
2d120f83
JS
1445 wxMemoryDC* memDC = (wxMemoryDC*) this;
1446 w = memDC->GetBitmap().GetWidth();
1447 h = memDC->GetBitmap().GetHeight();
1448 }
16c1f7f3 1449 else
2d120f83 1450 return;
16c1f7f3 1451 }
af0bb3b1 1452
2d120f83
JS
1453 wxBrush saveBrush = m_brush;
1454 SetBrush (m_backgroundBrush);
af0bb3b1 1455
2d120f83 1456 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, 0, w, h);
af0bb3b1 1457
2d120f83
JS
1458 if (m_window && m_window->GetBackingPixmap())
1459 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 0, 0, w, h);
af0bb3b1 1460
2d120f83 1461 m_brush = saveBrush;
af0bb3b1 1462}
4bb6408c 1463
a367b9b3
JS
1464void wxWindowDC::Clear(const wxRect& rect)
1465{
af0bb3b1
VZ
1466 wxCHECK_RET( Ok(), "invalid dc" );
1467
2d120f83
JS
1468 int x = rect.x; int y = rect.y;
1469 int w = rect.width; int h = rect.height;
af0bb3b1 1470
2d120f83
JS
1471 wxBrush saveBrush = m_brush;
1472 SetBrush (m_backgroundBrush);
af0bb3b1 1473
2d120f83 1474 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
af0bb3b1 1475
2d120f83
JS
1476 if (m_window && m_window->GetBackingPixmap())
1477 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
af0bb3b1 1478
2d120f83 1479 m_brush = saveBrush;
af0bb3b1 1480}
a367b9b3 1481
dfc54541 1482void wxWindowDC::SetFont( const wxFont &font )
4bb6408c 1483{
af0bb3b1
VZ
1484 wxCHECK_RET( Ok(), "invalid dc" );
1485
2d120f83 1486 m_font = font;
af0bb3b1 1487
2d120f83 1488 if (!m_font.Ok())
e97f20a0 1489 {
7b65ea1a 1490 if ((m_oldFont != (WXFont) 0) && ((wxCoord) m_oldFont != -1))
2d120f83
JS
1491 {
1492 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
af0bb3b1 1493
2d120f83
JS
1494 if (m_window && m_window->GetBackingPixmap())
1495 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1496 }
1497 return;
e97f20a0 1498 }
af0bb3b1 1499
2d120f83 1500 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
af0bb3b1 1501
2d120f83
JS
1502 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1503 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
af0bb3b1 1504
2d120f83
JS
1505 if (m_window && m_window->GetBackingPixmap())
1506 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
af0bb3b1 1507}
4bb6408c 1508
dfc54541 1509void wxWindowDC::SetPen( const wxPen &pen )
4bb6408c 1510{
af0bb3b1
VZ
1511 wxCHECK_RET( Ok(), "invalid dc" );
1512
2d120f83
JS
1513 m_pen = pen;
1514 if (!m_pen.Ok())
1515 return;
af0bb3b1 1516
2d120f83
JS
1517 wxBitmap oldStipple = m_currentStipple;
1518 int oldStyle = m_currentStyle;
1519 int oldFill = m_currentFill;
1520 int old_pen_width = m_currentPenWidth;
1521 int old_pen_join = m_currentPenJoin;
1522 int old_pen_cap = m_currentPenCap;
1523 int old_pen_nb_dash = m_currentPenDashCount;
236a9de3 1524 wxMOTIFDash *old_pen_dash = m_currentPenDash;
af0bb3b1 1525
2d120f83
JS
1526 wxColour oldPenColour = m_currentColour;
1527 m_currentColour = m_pen.GetColour ();
1528 m_currentStyle = m_pen.GetStyle ();
1529 m_currentFill = m_pen.GetStyle (); // TODO?
1530 m_currentPenWidth = m_pen.GetWidth ();
1531 m_currentPenJoin = m_pen.GetJoin ();
1532 m_currentPenCap = m_pen.GetCap ();
1533 m_currentPenDashCount = m_pen.GetDashCount();
236a9de3 1534 m_currentPenDash = (wxMOTIFDash*)m_pen.GetDash();
af0bb3b1 1535
2d120f83
JS
1536 if (m_currentStyle == wxSTIPPLE)
1537 m_currentStipple = * m_pen.GetStipple ();
af0bb3b1 1538
2d120f83
JS
1539 bool sameStyle = (oldStyle == m_currentStyle &&
1540 oldFill == m_currentFill &&
1541 old_pen_join == m_currentPenJoin &&
1542 old_pen_cap == m_currentPenCap &&
1543 old_pen_nb_dash == m_currentPenDashCount &&
1544 old_pen_dash == m_currentPenDash &&
1545 old_pen_width == m_currentPenWidth);
af0bb3b1 1546
2d120f83
JS
1547 bool sameColour = (oldPenColour.Ok () &&
1548 (oldPenColour.Red () == m_currentColour.Red ()) &&
1549 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1550 (oldPenColour.Green () == m_currentColour.Green ()) &&
1551 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1552
2d120f83 1553 if (!sameStyle || !GetOptimization())
16c1f7f3 1554 {
2d120f83
JS
1555 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1556 if (scaled_width < 0)
1557 scaled_width = 0;
af0bb3b1 1558
2d120f83
JS
1559 int style;
1560 int join;
1561 int cap;
236a9de3
RL
1562 static const wxMOTIFDash dotted[] = {2, 5};
1563 static const wxMOTIFDash short_dashed[] = {4, 4};
1564 static const wxMOTIFDash long_dashed[] = {4, 8};
1565 static const wxMOTIFDash dotted_dashed[] = {6, 6, 2, 6};
af0bb3b1 1566
2d120f83
JS
1567 // We express dash pattern in pen width unit, so we are
1568 // independent of zoom factor and so on...
1569 int req_nb_dash;
236a9de3 1570 const wxMOTIFDash *req_dash;
af0bb3b1 1571
2d120f83
JS
1572 switch (m_pen.GetStyle ())
1573 {
16c1f7f3 1574 case wxUSER_DASH:
2d120f83
JS
1575 req_nb_dash = m_currentPenDashCount;
1576 req_dash = m_currentPenDash;
1577 style = LineOnOffDash;
1578 break;
16c1f7f3 1579 case wxDOT:
2d120f83
JS
1580 req_nb_dash = 2;
1581 req_dash = dotted;
1582 style = LineOnOffDash;
1583 break;
16c1f7f3 1584 case wxSHORT_DASH:
2d120f83
JS
1585 req_nb_dash = 2;
1586 req_dash = short_dashed;
1587 style = LineOnOffDash;
1588 break;
16c1f7f3 1589 case wxLONG_DASH:
2d120f83
JS
1590 req_nb_dash = 2;
1591 req_dash = long_dashed;
1592 style = LineOnOffDash;
1593 break;
16c1f7f3 1594 case wxDOT_DASH:
2d120f83
JS
1595 req_nb_dash = 4;
1596 req_dash = dotted_dashed;
1597 style = LineOnOffDash;
1598 break;
16c1f7f3
JS
1599 case wxSTIPPLE:
1600 case wxSOLID:
1601 case wxTRANSPARENT:
1602 default:
2d120f83 1603 style = LineSolid;
236a9de3 1604 req_dash = (wxMOTIFDash*)NULL;
2d120f83 1605 req_nb_dash = 0;
16c1f7f3 1606 }
af0bb3b1 1607
2d120f83 1608 if (req_dash && req_nb_dash)
16c1f7f3 1609 {
236a9de3 1610 wxMOTIFDash *real_req_dash = new wxMOTIFDash[req_nb_dash];
2d120f83
JS
1611 if (real_req_dash)
1612 {
1613 int factor = scaled_width == 0 ? 1 : scaled_width;
1614 for (int i = 0; i < req_nb_dash; i++)
1615 real_req_dash[i] = req_dash[i] * factor;
1616 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
af0bb3b1 1617
2d120f83
JS
1618 if (m_window && m_window->GetBackingPixmap())
1619 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1620 delete[]real_req_dash;
1621 }
1622 else
1623 {
1624 // No Memory. We use non-scaled dash pattern...
1625 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
af0bb3b1 1626
2d120f83
JS
1627 if (m_window && m_window->GetBackingPixmap())
1628 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1629 }
16c1f7f3 1630 }
af0bb3b1 1631
2d120f83
JS
1632 switch (m_pen.GetCap ())
1633 {
16c1f7f3 1634 case wxCAP_PROJECTING:
2d120f83
JS
1635 cap = CapProjecting;
1636 break;
16c1f7f3 1637 case wxCAP_BUTT:
2d120f83
JS
1638 cap = CapButt;
1639 break;
16c1f7f3
JS
1640 case wxCAP_ROUND:
1641 default:
2d120f83
JS
1642 cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1643 break;
1644 }
af0bb3b1 1645
2d120f83
JS
1646 switch (m_pen.GetJoin ())
1647 {
16c1f7f3 1648 case wxJOIN_BEVEL:
2d120f83
JS
1649 join = JoinBevel;
1650 break;
16c1f7f3 1651 case wxJOIN_MITER:
2d120f83
JS
1652 join = JoinMiter;
1653 break;
16c1f7f3
JS
1654 case wxJOIN_ROUND:
1655 default:
2d120f83
JS
1656 join = JoinRound;
1657 break;
1658 }
af0bb3b1 1659
2d120f83 1660 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
af0bb3b1 1661
2d120f83
JS
1662 if (m_window && m_window->GetBackingPixmap())
1663 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
16c1f7f3 1664 }
af0bb3b1 1665
16c1f7f3
JS
1666 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1667 {
2d120f83 1668 Pixmap myStipple;
af0bb3b1 1669
2d120f83 1670 oldStipple = wxNullBitmap; // For later reset!!
af0bb3b1 1671
2d120f83
JS
1672 switch (m_currentFill)
1673 {
16c1f7f3 1674 case wxBDIAGONAL_HATCH:
2d120f83
JS
1675 if (bdiag == (Pixmap) 0)
1676 bdiag = XCreateBitmapFromData ((Display*) m_display,
1677 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1678 bdiag_bits, bdiag_width, bdiag_height);
1679 myStipple = bdiag;
1680 break;
16c1f7f3 1681 case wxFDIAGONAL_HATCH:
2d120f83
JS
1682 if (fdiag == (Pixmap) 0)
1683 fdiag = XCreateBitmapFromData ((Display*) m_display,
1684 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1685 fdiag_bits, fdiag_width, fdiag_height);
1686 myStipple = fdiag;
1687 break;
16c1f7f3 1688 case wxCROSS_HATCH:
2d120f83
JS
1689 if (cross == (Pixmap) 0)
1690 cross = XCreateBitmapFromData ((Display*) m_display,
1691 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1692 cross_bits, cross_width, cross_height);
1693 myStipple = cross;
1694 break;
16c1f7f3 1695 case wxHORIZONTAL_HATCH:
2d120f83
JS
1696 if (horiz == (Pixmap) 0)
1697 horiz = XCreateBitmapFromData ((Display*) m_display,
1698 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1699 horiz_bits, horiz_width, horiz_height);
1700 myStipple = horiz;
1701 break;
16c1f7f3 1702 case wxVERTICAL_HATCH:
2d120f83
JS
1703 if (verti == (Pixmap) 0)
1704 verti = XCreateBitmapFromData ((Display*) m_display,
1705 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1706 verti_bits, verti_width, verti_height);
1707 myStipple = verti;
1708 break;
16c1f7f3
JS
1709 case wxCROSSDIAG_HATCH:
1710 default:
2d120f83
JS
1711 if (cdiag == (Pixmap) 0)
1712 cdiag = XCreateBitmapFromData ((Display*) m_display,
1713 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1714 cdiag_bits, cdiag_width, cdiag_height);
1715 myStipple = cdiag;
1716 break;
1717 }
1718 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
af0bb3b1 1719
2d120f83
JS
1720 if (m_window && m_window->GetBackingPixmap())
1721 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
16c1f7f3
JS
1722 }
1723 else if (m_currentStipple.Ok()
2d120f83 1724 && ((m_currentStipple != oldStipple) || !GetOptimization()))
16c1f7f3 1725 {
2d120f83 1726 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
af0bb3b1 1727
2d120f83
JS
1728 if (m_window && m_window->GetBackingPixmap())
1729 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
16c1f7f3 1730 }
af0bb3b1 1731
16c1f7f3
JS
1732 if ((m_currentFill != oldFill) || !GetOptimization())
1733 {
2d120f83 1734 int fill_style;
af0bb3b1 1735
2d120f83
JS
1736 if (m_currentFill == wxSTIPPLE)
1737 fill_style = FillStippled;
1738 else if (IS_HATCH (m_currentFill))
1739 fill_style = FillStippled;
1740 else
1741 fill_style = FillSolid;
1742 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1743 if (m_window && m_window->GetBackingPixmap())
1744 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
16c1f7f3 1745 }
af0bb3b1 1746
16c1f7f3
JS
1747 // must test m_logicalFunction, because it involves background!
1748 if (!sameColour || !GetOptimization()
2d120f83 1749 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
16c1f7f3 1750 {
2d120f83
JS
1751 int pixel = -1;
1752 if (m_pen.GetStyle () == wxTRANSPARENT)
1753 pixel = m_backgroundPixel;
1754 else if (!m_colour)
16c1f7f3 1755 {
2d120f83
JS
1756 unsigned char red = m_pen.GetColour ().Red ();
1757 unsigned char blue = m_pen.GetColour ().Blue ();
1758 unsigned char green = m_pen.GetColour ().Green ();
1759 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1760 && green == (unsigned char) 255)
1761 {
1762 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1763 m_currentColour = *wxWHITE;
1764 m_pen.GetColour().SetPixel(pixel);
1765 m_currentColour.SetPixel(pixel);
1766 }
1767 else
1768 {
1769 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1770 m_currentColour = *wxBLACK;
1771 m_pen.GetColour().SetPixel(pixel);
1772 }
16c1f7f3
JS
1773 }
1774 else
1775 {
2d120f83
JS
1776 pixel = m_pen.GetColour ().AllocColour(m_display);
1777 m_currentColour.SetPixel(pixel);
16c1f7f3 1778 }
af0bb3b1 1779
2d120f83
JS
1780 // Finally, set the GC to the required colour
1781 if (pixel > -1)
16c1f7f3 1782 {
2d120f83
JS
1783 if (m_logicalFunction == wxXOR)
1784 {
1785 XGCValues values;
1786 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1787 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1788 if (m_window && m_window->GetBackingPixmap())
1789 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1790 }
1791 else
1792 {
1793 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1794 if (m_window && m_window->GetBackingPixmap())
1795 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1796 }
16c1f7f3
JS
1797 }
1798 }
2d120f83
JS
1799 else
1800 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
af0bb3b1 1801
2d120f83 1802 m_autoSetting = 0;
af0bb3b1 1803}
4bb6408c 1804
dfc54541 1805void wxWindowDC::SetBrush( const wxBrush &brush )
4bb6408c 1806{
af0bb3b1
VZ
1807 wxCHECK_RET( Ok(), "invalid dc" );
1808
2d120f83 1809 m_brush = brush;
af0bb3b1 1810
2d120f83
JS
1811 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1812 return;
af0bb3b1 1813
2d120f83
JS
1814 int oldFill = m_currentFill;
1815 wxBitmap oldStipple = m_currentStipple;
af0bb3b1 1816
2d120f83 1817 m_autoSetting |= 0x1;
af0bb3b1 1818
2d120f83
JS
1819 m_currentFill = m_brush.GetStyle ();
1820 if (m_currentFill == wxSTIPPLE)
1821 m_currentStipple = * m_brush.GetStipple ();
af0bb3b1 1822
2d120f83
JS
1823 wxColour oldBrushColour(m_currentColour);
1824 m_currentColour = m_brush.GetColour ();
af0bb3b1 1825
2d120f83
JS
1826 bool sameColour = (oldBrushColour.Ok () &&
1827 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1828 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1829 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1830 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1831
2d120f83
JS
1832 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1833 {
1834 switch (brush.GetStyle ())
1835 {
16c1f7f3 1836 case wxTRANSPARENT:
2d120f83 1837 break;
16c1f7f3
JS
1838 case wxBDIAGONAL_HATCH:
1839 case wxCROSSDIAG_HATCH:
1840 case wxFDIAGONAL_HATCH:
1841 case wxCROSS_HATCH:
1842 case wxHORIZONTAL_HATCH:
1843 case wxVERTICAL_HATCH:
1844 case wxSTIPPLE:
2d120f83
JS
1845 {
1846 // Chris Breeze 23/07/97: use background mode to determine whether
1847 // fill style should be solid or transparent
1848 int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled);
1849 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1850 if (m_window && m_window->GetBackingPixmap())
1851 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1852 }
1853 break;
16c1f7f3
JS
1854 case wxSOLID:
1855 default:
2d120f83
JS
1856 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1857 if (m_window && m_window->GetBackingPixmap())
1858 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, FillSolid);
1859 }
1860 }
af0bb3b1 1861
2d120f83 1862 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
16c1f7f3 1863 {
2d120f83 1864 Pixmap myStipple;
af0bb3b1 1865
2d120f83
JS
1866 switch (m_currentFill)
1867 {
16c1f7f3 1868 case wxBDIAGONAL_HATCH:
2d120f83
JS
1869 if (bdiag == (Pixmap) 0)
1870 bdiag = XCreateBitmapFromData ((Display*) m_display,
1871 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1872 bdiag_bits, bdiag_width, bdiag_height);
1873 myStipple = bdiag;
1874 break;
16c1f7f3 1875 case wxFDIAGONAL_HATCH:
2d120f83
JS
1876 if (fdiag == (Pixmap) 0)
1877 fdiag = XCreateBitmapFromData ((Display*) m_display,
1878 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1879 fdiag_bits, fdiag_width, fdiag_height);
1880 myStipple = fdiag;
1881 break;
16c1f7f3 1882 case wxCROSS_HATCH:
2d120f83
JS
1883 if (cross == (Pixmap) 0)
1884 cross = XCreateBitmapFromData ((Display*) m_display,
1885 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1886 cross_bits, cross_width, cross_height);
1887 myStipple = cross;
1888 break;
16c1f7f3 1889 case wxHORIZONTAL_HATCH:
2d120f83
JS
1890 if (horiz == (Pixmap) 0)
1891 horiz = XCreateBitmapFromData ((Display*) m_display,
1892 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1893 horiz_bits, horiz_width, horiz_height);
1894 myStipple = horiz;
1895 break;
16c1f7f3 1896 case wxVERTICAL_HATCH:
2d120f83
JS
1897 if (verti == (Pixmap) 0)
1898 verti = XCreateBitmapFromData ((Display*) m_display,
1899 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1900 verti_bits, verti_width, verti_height);
1901 myStipple = verti;
1902 break;
16c1f7f3
JS
1903 case wxCROSSDIAG_HATCH:
1904 default:
2d120f83
JS
1905 if (cdiag == (Pixmap) 0)
1906 cdiag = XCreateBitmapFromData ((Display*) m_display,
1907 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1908 cdiag_bits, cdiag_width, cdiag_height);
1909 myStipple = cdiag;
1910 break;
1911 }
1912 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
af0bb3b1 1913
2d120f83
JS
1914 if (m_window && m_window->GetBackingPixmap())
1915 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
16c1f7f3
JS
1916 }
1917 // X can forget the stipple value when resizing a window (apparently)
1918 // so always set the stipple.
1919 else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1920 {
2d120f83
JS
1921 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1922 if (m_window && m_window->GetBackingPixmap())
1923 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
16c1f7f3 1924 }
af0bb3b1 1925
16c1f7f3
JS
1926 // must test m_logicalFunction, because it involves background!
1927 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
1928 {
2d120f83
JS
1929 int pixel = -1;
1930 if (!m_colour)
1931 {
1932 // Policy - on a monochrome screen, all brushes are white,
1933 // except when they're REALLY black!!!
1934 unsigned char red = m_brush.GetColour ().Red ();
1935 unsigned char blue = m_brush.GetColour ().Blue ();
1936 unsigned char green = m_brush.GetColour ().Green ();
af0bb3b1 1937
2d120f83
JS
1938 if (red == (unsigned char) 0 && blue == (unsigned char) 0
1939 && green == (unsigned char) 0)
16c1f7f3 1940 {
2d120f83
JS
1941 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1942 m_currentColour = *wxBLACK;
1943 m_brush.GetColour().SetPixel(pixel);
1944 m_currentColour.SetPixel(pixel);
16c1f7f3 1945 }
2d120f83 1946 else
16c1f7f3 1947 {
2d120f83
JS
1948 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1949 m_currentColour = *wxWHITE;
1950 m_brush.GetColour().SetPixel(pixel);
1951 m_currentColour.SetPixel(pixel);
16c1f7f3 1952 }
af0bb3b1 1953
2d120f83
JS
1954 // N.B. comment out the above line and uncomment the following lines
1955 // if you want non-white colours to be black on a monochrome display.
1956 /*
1957 if (red == (unsigned char )255 && blue == (unsigned char)255
1958 && green == (unsigned char)255)
1959 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1960 else
1961 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1962 */
1963 }
1964 else if (m_brush.GetStyle () != wxTRANSPARENT)
16c1f7f3 1965 {
2d120f83
JS
1966 pixel = m_brush.GetColour().AllocColour(m_display);
1967 m_currentColour.SetPixel(pixel);
16c1f7f3 1968 }
2d120f83 1969 if (pixel > -1)
16c1f7f3 1970 {
2d120f83
JS
1971 // Finally, set the GC to the required colour
1972 if (m_logicalFunction == wxXOR)
1973 {
1974 XGCValues values;
1975 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1976 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1977 if (m_window && m_window->GetBackingPixmap())
1978 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1979 }
1980 else
1981 {
1982 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1983 if (m_window && m_window->GetBackingPixmap())
1984 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1985 }
16c1f7f3 1986 }
16c1f7f3 1987 }
2d120f83
JS
1988 else
1989 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
af0bb3b1 1990}
4bb6408c 1991
dfc54541 1992void wxWindowDC::SetBackground( const wxBrush &brush )
4bb6408c 1993{
af0bb3b1
VZ
1994 wxCHECK_RET( Ok(), "invalid dc" );
1995
2d120f83 1996 m_backgroundBrush = brush;
af0bb3b1 1997
2d120f83
JS
1998 if (!m_backgroundBrush.Ok())
1999 return;
af0bb3b1 2000
2d120f83 2001 int pixel = m_backgroundBrush.GetColour().AllocColour(m_display);
a91b47e8
JS
2002
2003 // New behaviour, 10/2/99: setting the background brush of a DC
2004 // doesn't affect the window background colour.
2005/*
2d120f83
JS
2006 // XSetWindowBackground doesn't work for non-Window pixmaps
2007 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2008 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
a91b47e8 2009*/
af0bb3b1 2010
2d120f83
JS
2011 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2012 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2013 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
2014 if (m_window && m_window->GetBackingPixmap())
2015 XSetBackground ((Display*) m_display,(GC) m_gcBacking, pixel);
af0bb3b1 2016}
4bb6408c 2017
dfc54541 2018void wxWindowDC::SetLogicalFunction( int function )
4bb6408c 2019{
af0bb3b1
VZ
2020 wxCHECK_RET( Ok(), "invalid dc" );
2021
2d120f83 2022 int x_function;
af0bb3b1 2023
2d120f83
JS
2024 /* MATTHEW: [9] */
2025 if (m_logicalFunction == function)
2026 return;
af0bb3b1 2027
2d120f83 2028 switch (function)
16c1f7f3
JS
2029 {
2030 case wxCLEAR:
2d120f83
JS
2031 x_function = GXclear;
2032 break;
16c1f7f3 2033 case wxXOR:
2d120f83
JS
2034 x_function = GXxor;
2035 break;
16c1f7f3 2036 case wxINVERT:
2d120f83
JS
2037 x_function = GXinvert;
2038 break;
16c1f7f3 2039 case wxOR_REVERSE:
2d120f83
JS
2040 x_function = GXorReverse;
2041 break;
16c1f7f3 2042 case wxAND_REVERSE:
2d120f83
JS
2043 x_function = GXandReverse;
2044 break;
16c1f7f3 2045 case wxAND:
2d120f83
JS
2046 x_function = GXand;
2047 break;
16c1f7f3 2048 case wxOR:
2d120f83
JS
2049 x_function = GXor;
2050 break;
16c1f7f3 2051 case wxAND_INVERT:
2d120f83
JS
2052 x_function = GXandInverted;
2053 break;
16c1f7f3 2054 case wxNO_OP:
2d120f83
JS
2055 x_function = GXnoop;
2056 break;
16c1f7f3 2057 case wxNOR:
2d120f83
JS
2058 x_function = GXnor;
2059 break;
16c1f7f3 2060 case wxEQUIV:
2d120f83
JS
2061 x_function = GXequiv;
2062 break;
16c1f7f3 2063 case wxSRC_INVERT:
2d120f83
JS
2064 x_function = GXcopyInverted;
2065 break;
16c1f7f3 2066 case wxOR_INVERT:
2d120f83
JS
2067 x_function = GXorInverted;
2068 break;
16c1f7f3 2069 case wxNAND:
2d120f83
JS
2070 x_function = GXnand;
2071 break;
16c1f7f3 2072 case wxSET:
2d120f83
JS
2073 x_function = GXset;
2074 break;
16c1f7f3
JS
2075 case wxCOPY:
2076 default:
2d120f83
JS
2077 x_function = GXcopy;
2078 break;
16c1f7f3 2079 }
af0bb3b1 2080
2d120f83
JS
2081 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
2082 if (m_window && m_window->GetBackingPixmap())
2083 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
af0bb3b1 2084
2d120f83
JS
2085 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
2086 /* MATTHEW: [9] Need to redo pen simply */
2087 m_autoSetting |= 0x2;
af0bb3b1 2088
2d120f83 2089 m_logicalFunction = function;
af0bb3b1
VZ
2090
2091}
4bb6408c 2092
dfc54541 2093void wxWindowDC::SetTextForeground( const wxColour &col )
4bb6408c 2094{
af0bb3b1
VZ
2095 wxCHECK_RET( Ok(), "invalid dc" );
2096
2097 if (m_textForegroundColour == col)
2098 return;
2099
2d120f83 2100 m_textForegroundColour = col;
af0bb3b1
VZ
2101
2102}
4bb6408c 2103
dfc54541 2104void wxWindowDC::SetTextBackground( const wxColour &col )
4bb6408c 2105{
af0bb3b1
VZ
2106 wxCHECK_RET( Ok(), "invalid dc" );
2107
2108 if (m_textBackgroundColour == col)
2109 return;
2110
2d120f83 2111 m_textBackgroundColour = col;
af0bb3b1
VZ
2112 if (!m_textBackgroundColour.Ok())
2113 return;
2114}
4bb6408c 2115
dfc54541 2116void wxWindowDC::SetBackgroundMode( int mode )
4bb6408c 2117{
2d120f83 2118 m_backgroundMode = mode;
af0bb3b1 2119}
16c1f7f3
JS
2120
2121void wxWindowDC::SetPalette( const wxPalette& palette )
2122{
2d120f83
JS
2123 if (m_window)
2124 {
2125 if (palette.Ok())
2126 /* Use GetXColormap */
2127 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2128 (Colormap) palette.GetXColormap());
2129 else
2130 /* Use wxGetMainColormap */
2131 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2132 (Colormap) wxTheApp->GetMainColormap(m_display));
2133 }
af0bb3b1 2134}
4bb6408c 2135
16c1f7f3 2136// Helper function
af0bb3b1 2137void wxWindowDC::SetDCClipping()
4bb6408c 2138{
2d120f83 2139 // m_userRegion is the region set by calling SetClippingRegion
af0bb3b1 2140
2d120f83
JS
2141 if (m_currentRegion)
2142 XDestroyRegion ((Region) m_currentRegion);
af0bb3b1 2143
2d120f83
JS
2144 // We need to take into account
2145 // clipping imposed on a window by a repaint.
2146 // We'll combine it with the user region. But for now,
2147 // just use the currently-defined user clipping region.
2148 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
2149 m_currentRegion = (WXRegion) XCreateRegion ();
2150 else
2151 m_currentRegion = (WXRegion) NULL;
af0bb3b1 2152
2d120f83
JS
2153 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2154 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
2155 else if (m_userRegion)
2156 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
2157 else if (m_window && m_window->GetUpdateRegion().Ok())
af0bb3b1 2158 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
2d120f83 2159 (Region) m_currentRegion);
af0bb3b1 2160
2d120f83 2161 if (m_currentRegion)
16c1f7f3 2162 {
2d120f83 2163 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
16c1f7f3 2164 }
2d120f83 2165 else
16c1f7f3 2166 {
2d120f83 2167 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
16c1f7f3 2168 }
af0bb3b1 2169
16c1f7f3 2170}
4bb6408c 2171
7b65ea1a 2172void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
4bb6408c 2173{
33caefb3 2174 wxDC::DoSetClippingRegion( x, y, width, height );
af0bb3b1 2175
2d120f83
JS
2176 if (m_userRegion)
2177 XDestroyRegion ((Region) m_userRegion);
2178 m_userRegion = (WXRegion) XCreateRegion ();
2179 XRectangle r;
2180 r.x = XLOG2DEV (x);
2181 r.y = YLOG2DEV (y);
2182 r.width = XLOG2DEVREL(width);
2183 r.height = YLOG2DEVREL(height);
2184 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
af0bb3b1 2185
2d120f83 2186 SetDCClipping ();
af0bb3b1 2187
2d120f83
JS
2188 // Needs to work differently for Pixmap: without this,
2189 // there's a nasty (Display*) m_display bug. 8/12/94
2190 if (m_window && m_window->GetBackingPixmap())
2191 {
2192 XRectangle rects[1];
af0bb3b1 2193 rects[0].x = XLOG2DEV_2(x);
2d120f83
JS
2194 rects[0].y = YLOG2DEV_2(y);
2195 rects[0].width = XLOG2DEVREL(width);
2196 rects[0].height = YLOG2DEVREL(height);
2197 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2198 }
af0bb3b1 2199}
4bb6408c 2200
af0bb3b1 2201void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
a724d789 2202{
2d120f83 2203 wxRect box = region.GetBox();
af0bb3b1 2204
33caefb3 2205 wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height );
af0bb3b1 2206
2d120f83
JS
2207 if (m_userRegion)
2208 XDestroyRegion ((Region) m_userRegion);
2209 m_userRegion = (WXRegion) XCreateRegion ();
af0bb3b1 2210
2d120f83 2211 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
af0bb3b1 2212
2d120f83 2213 SetDCClipping ();
af0bb3b1 2214
2d120f83
JS
2215 // Needs to work differently for Pixmap: without this,
2216 // there's a nasty (Display*) m_display bug. 8/12/94
2217 if (m_window && m_window->GetBackingPixmap())
2218 {
2219 XRectangle rects[1];
2220 rects[0].x = XLOG2DEV_2(box.x);
2221 rects[0].y = YLOG2DEV_2(box.y);
2222 rects[0].width = XLOG2DEVREL(box.width);
2223 rects[0].height = YLOG2DEVREL(box.height);
2224 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2225 }
af0bb3b1 2226}
a724d789
JS
2227
2228
af0bb3b1 2229void wxWindowDC::DestroyClippingRegion()
4bb6408c 2230{
2d120f83 2231 wxDC::DestroyClippingRegion();
af0bb3b1 2232
2d120f83
JS
2233 if (m_userRegion)
2234 XDestroyRegion ((Region) m_userRegion);
2235 m_userRegion = NULL;
af0bb3b1 2236
2d120f83 2237 SetDCClipping ();
af0bb3b1 2238
2d120f83
JS
2239 XGCValues gc_val;
2240 gc_val.clip_mask = None;
2241 if (m_window && m_window->GetBackingPixmap())
2242 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
4bb6408c
JS
2243}
2244
af0bb3b1
VZ
2245// Resolution in pixels per logical inch
2246wxSize wxWindowDC::GetPPI() const
4bb6408c 2247{
af0bb3b1 2248 return wxSize(100, 100);
4bb6408c
JS
2249}
2250
af0bb3b1 2251int wxWindowDC::GetDepth() const
7bcb11d3 2252{
af0bb3b1
VZ
2253 // TODO
2254 return 24;
7bcb11d3
JS
2255}
2256
96f201da
RR
2257
2258
2259
af0bb3b1
VZ
2260// ----------------------------------------------------------------------------
2261// wxPaintDC
2262// ----------------------------------------------------------------------------
55acd85e 2263
af0bb3b1 2264wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win)
55acd85e
JS
2265{
2266 wxRegion* region = NULL;
af0bb3b1 2267
55acd85e 2268 // Combine all the update rects into a region
af0bb3b1
VZ
2269 const wxRectList& updateRects(win->GetUpdateRects());
2270 if ( updateRects.GetCount() != 0 )
55acd85e 2271 {
af0bb3b1
VZ
2272 for ( wxRectList::Node *node = updateRects.GetFirst();
2273 node;
2274 node = node->GetNext() )
55acd85e 2275 {
af0bb3b1
VZ
2276 wxRect* rect = node->GetData();
2277
55acd85e
JS
2278 if (!region)
2279 region = new wxRegion(*rect);
2280 else
2281 // TODO: is this correct? In SetDCClipping above,
2282 // XIntersectRegion is used to combine paint and user
2283 // regions. XIntersectRegion appears to work in that case...
2284 region->Union(*rect);
2285 }
2286 }
2287 else
2288 {
2289 int cw, ch;
2290 win->GetClientSize(&cw, &ch);
2291 region = new wxRegion(wxRect(0, 0, cw, ch));
2292 }
af0bb3b1
VZ
2293
2294 win->SetUpdateRegion(*region);
2295
25f47127
JS
2296 wxRegion& theRegion(win->GetUpdateRegion());
2297 theRegion.SetRects(updateRects); // We also store in terms of rects, for iteration to work.
2298
55acd85e
JS
2299 // Set the clipping region. Any user-defined region will be combined with this
2300 // one in SetDCClipping.
2301 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
af0bb3b1 2302
55acd85e
JS
2303 delete region;
2304}
2305
2306wxPaintDC::~wxPaintDC()
2307{
2308 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2309 if (m_window)
af0bb3b1
VZ
2310 m_window->ClearUpdateRegion();
2311}
2312
2313// ----------------------------------------------------------------------------
2314// private functions
2315// ----------------------------------------------------------------------------
2316
2317/*
2318 Used when copying between drawables on different (Display*) m_displays. Not
2319 very fast, but better than giving up.
2320*/
2321
2322static void XCopyRemote(Display *src_display, Display *dest_display,
2323 Drawable src, Drawable dest,
2324 GC destgc,
2325 int srcx, int srcy,
2326 unsigned int w, unsigned int h,
2327 int destx, int desty,
2328 bool more, XImage **cache)
2329{
2330 XImage *image, *destimage;
2331 Colormap destcm, srccm;
2332 static const int CACHE_SIZE = 256;
2333
2334 unsigned int i, j;
2335 unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2336 int k, cache_pos, all_cache;
2337
2338 if (!cache || !*cache)
2339 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2340 else
2341 image = *cache;
2342
2343 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2344
2345 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2346 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2347
2348 cache_pos = 0;
2349 all_cache = FALSE;
2350
2351 for (i = 0; i < w; i++)
2352 for (j = 0; j < h; j++) {
2353 unsigned long pixel;
2354 XColor xcol;
2355
2356 pixel = XGetPixel(image, i, j);
2357 for (k = cache_pos; k--; )
2358 if (cachesrc[k] == pixel) {
2359 pixel = cachedest[k];
2360 goto install;
2361 }
2362 if (all_cache)
2363 for (k = CACHE_SIZE; k-- > cache_pos; )
2364 if (cachesrc[k] == pixel) {
2365 pixel = cachedest[k];
2366 goto install;
2367 }
2368
2369 cachesrc[cache_pos] = xcol.pixel = pixel;
2370 XQueryColor(src_display, srccm, &xcol);
2371 if (!XAllocColor(dest_display, destcm, &xcol))
2372 xcol.pixel = 0;
2373 cachedest[cache_pos] = pixel = xcol.pixel;
2374
2375 if (++cache_pos >= CACHE_SIZE) {
2376 cache_pos = 0;
2377 all_cache = TRUE;
2378 }
2379
2380install:
2381 XPutPixel(destimage, i, j, pixel);
2382 }
2383
2384 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2385 XDestroyImage(destimage);
2386
2387 if (more)
2388 *cache = image;
2389 else
2390 XDestroyImage(image);
2391}
2392
2393#if 0
2394
2395/* Helper function for 16-bit fonts */
2396static int str16len(const char *s)
2397{
2398 int count = 0;
2399
2400 while (s[0] && s[1]) {
2401 count++;
2402 s += 2;
2403 }
2404
2405 return count;
55acd85e
JS
2406}
2407
af0bb3b1 2408#endif // 0