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