]> git.saurik.com Git - wxWidgets.git/blame - src/motif/dcclient.cpp
use jast major.minor, not major.minor.micro, in the DLL names
[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
729be74d
MB
15 Under X, pens and brushes control some of the same X drawing
16 parameters. Therefore, it is impossible to independently maintain
17 the current pen and the current brush. Also, some settings depend on
18 the current logical function. The m_currentFill, etc. instance
19 variables remember state across the brush and pen.
af0bb3b1
VZ
20
21 Since pens are used more than brushes, the autoSetting flag is used to
22 indicate that a brush was recently used, and SetPen must be called to
23 reinstall the current pen's parameters. If autoSetting includes 0x2, then the
24 pens color may need to be set based on XOR.
25
26 There is, unfortunately, some confusion between setting the current pen/brush
27 and actually installing the brush/pen parameters. Both functionalies are
28 perform by SetPen and SetBrush. C'est la vie.
16c1f7f3
JS
29*/
30
af0bb3b1
VZ
31// ============================================================================
32// declarations
33// ============================================================================
34
35// ----------------------------------------------------------------------------
36// headers
37// ----------------------------------------------------------------------------
38
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;
69c44812 138 m_currentPenDash = (wxX11Dash*) 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;
69c44812 163 m_currentPenDash = (wxX11Dash*) 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
729be74d
MB
1240void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y,
1241 double angle )
95724b1a
VZ
1242{
1243 if (angle == 0.0)
1244 {
1245 DrawText(text, x, y);
1246 return;
1247 }
1248
1249 wxCHECK_RET( Ok(), "invalid dc" );
1250
729be74d
MB
1251 int oldBackgroundPixel = -1;
1252 int oldForegroundPixel = -1;
1253 int foregroundPixel = -1;
1254 int backgroundPixel = -1;
1255
1256 if (m_textBackgroundColour.Ok())
1257 {
1258 oldBackgroundPixel = m_backgroundPixel;
1259 backgroundPixel = m_textBackgroundColour.AllocColour(m_display);
1260 }
1261 if (m_textForegroundColour.Ok())
1262 {
1263 oldForegroundPixel = m_currentColour.GetPixel();
1264
1265 if( m_textForegroundColour.GetPixel() <= -1 )
1266 CalculatePixel( m_textForegroundColour,
1267 m_textForegroundColour, TRUE);
1268
1269 foregroundPixel = m_textForegroundColour.GetPixel();
1270 }
1271
95724b1a
VZ
1272 // Since X draws from the baseline of the text, must add the text height
1273 int cx = 0;
1274 int cy = 0;
1275 int ascent = 0;
729be74d 1276 int slen = text.length();
95724b1a
VZ
1277
1278 if (m_font.Ok())
1279 {
1280 // Calculate text extent.
729be74d
MB
1281 WXFontStructPtr pFontStruct =
1282 m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
95724b1a
VZ
1283 int direction, descent;
1284 XCharStruct overall_return;
1285#if 0
1286 if (use16)
729be74d
MB
1287 (void)XTextExtents16((XFontStruct*) pFontStruct,
1288 (XChar2b *)(const char*) text,
1289 slen, &direction,
95724b1a
VZ
1290 &ascent, &descent, &overall_return);
1291 else
1292#endif // 0
729be74d
MB
1293 (void)XTextExtents((XFontStruct*) pFontStruct,
1294 (char*)text.c_str(), slen, &direction,
95724b1a
VZ
1295 &ascent, &descent, &overall_return);
1296
1297 cx = overall_return.width;
1298 cy = ascent + descent;
1299 }
1300
1301 wxBitmap src(cx, cy);
1302 wxMemoryDC dc;
1303 dc.SelectObject(src);
1304 dc.SetFont(GetFont());
1305 dc.SetBackground(*wxWHITE_BRUSH);
1306 dc.SetBrush(*wxBLACK_BRUSH);
1307 dc.Clear();
1308 dc.DrawText(text, 0, 0);
1309 dc.SetFont(wxNullFont);
1310
1311 // Calculate the size of the rotated bounding box.
1312 double dx = cos(angle / 180.0 * M_PI);
1313 double dy = sin(angle / 180.0 * M_PI);
729be74d 1314 double x4 = cy * dy;
95724b1a
VZ
1315 double y4 = cy * dx;
1316 double x3 = cx * dx;
729be74d 1317 double y3 = -cx * dy;
95724b1a
VZ
1318 double x2 = x3 + x4;
1319 double y2 = y3 + y4;
1320 double x1 = x;
1321 double y1 = y;
1322
1323 // Create image from the source bitmap after writing the text into it.
79f1dd05 1324 wxImage image = src.ConvertToImage();
95724b1a
VZ
1325
1326 int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
1327 int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
1328 int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
1329 int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
1330
729be74d
MB
1331 bool lastFore = false, lastBack = false;
1332
95724b1a
VZ
1333 // This rotates counterclockwise around the top left corner.
1334 for (int rx = minx; rx < maxx; rx++)
1335 {
1336 for (int ry = miny; ry < maxy; ry++)
1337 {
1338 // transform dest coords to source coords
729be74d
MB
1339 int sx = (int) (rx * dx - ry * dy + 0.5);
1340 int sy = - (int) (-ry * dx - rx * dy + 0.5);
95724b1a
VZ
1341 if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
1342 {
729be74d
MB
1343 bool textPixel = image.GetRed(sx, sy) == 0;
1344
1345 if (!textPixel && m_backgroundMode != wxSOLID)
1346 continue;
1347
1348 wxCoord ox = (wxCoord) (x1 + rx),
1349 oy = (wxCoord) (y1 + ry);
95724b1a 1350 // draw black pixels, ignore white ones (i.e. transparent b/g)
729be74d 1351 if (textPixel && !lastFore)
95724b1a 1352 {
729be74d
MB
1353 XSetForeground ((Display*) m_display, (GC) m_gc,
1354 foregroundPixel);
1355 lastFore = true;
1356 lastBack = false;
95724b1a 1357 }
729be74d 1358 else if (!textPixel && !lastBack)
95724b1a 1359 {
729be74d
MB
1360 XSetForeground ((Display*) m_display, (GC) m_gc,
1361 backgroundPixel);
1362 lastFore = false;
1363 lastBack = true;
95724b1a 1364 }
95724b1a 1365
729be74d
MB
1366 XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap,
1367 (GC) m_gc, XLOG2DEV (ox), YLOG2DEV (oy));
95724b1a 1368 if (m_window && m_window->GetBackingPixmap())
729be74d
MB
1369 XDrawPoint ((Display*) m_display,
1370 (Pixmap) m_window->GetBackingPixmap(),
1371 (GC) m_gcBacking,
1372 XLOG2DEV_2 (ox), YLOG2DEV_2 (oy));
95724b1a
VZ
1373 }
1374 }
729be74d 1375 }
95724b1a 1376
729be74d
MB
1377 if (oldBackgroundPixel > -1)
1378 {
1379 XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
95724b1a 1380 if (m_window && m_window->GetBackingPixmap())
729be74d
MB
1381 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1382 oldBackgroundPixel);
1383 }
1384 if (oldForegroundPixel > -1)
1385 {
1386 XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1387 if (m_window && m_window->GetBackingPixmap())
1388 XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1389 oldForegroundPixel);
95724b1a 1390 }
95724b1a 1391
729be74d
MB
1392 CalcBoundingBox (minx, miny);
1393 CalcBoundingBox (maxx, maxy);
95724b1a
VZ
1394}
1395
af0bb3b1 1396bool wxWindowDC::CanGetTextExtent() const
4bb6408c 1397{
2d120f83 1398 return TRUE;
af0bb3b1 1399}
4bb6408c 1400
7b65ea1a
MB
1401void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1402 wxCoord *descent, wxCoord *externalLeading,
af0bb3b1 1403 wxFont *font ) const
4bb6408c 1404{
af0bb3b1
VZ
1405 wxCHECK_RET( Ok(), "invalid dc" );
1406
2d120f83
JS
1407 wxFont* theFont = font;
1408 if (!theFont)
af0bb3b1
VZ
1409 theFont = (wxFont *)&m_font; // const_cast
1410
2d120f83
JS
1411 if (!theFont->Ok())
1412 {
1413 // TODO: this should be an error log function
1414 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
af0bb3b1 1415
33caefb3
RR
1416 if (width) *width = -1;
1417 if (height) *height = -1;
2d120f83
JS
1418 return;
1419 }
af0bb3b1 1420
2d120f83 1421 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
af0bb3b1 1422
2d120f83
JS
1423 int direction, ascent, descent2;
1424 XCharStruct overall;
1425 int slen;
af0bb3b1
VZ
1426
1427#if 0
1428 if (use16)
1429 slen = str16len(string);
1430 else
1431#endif // 0
1432 slen = strlen(string);
1433
1434#if 0
2d120f83
JS
1435 if (use16)
1436 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1437 &ascent, &descent2, &overall);
1438 else
af0bb3b1 1439#endif // 0
2d120f83
JS
1440 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1441 &ascent, &descent2, &overall);
af0bb3b1 1442
33caefb3
RR
1443 if (width) *width = XDEV2LOGREL (overall.width);
1444 if (height) *height = YDEV2LOGREL (ascent + descent2);
2d120f83
JS
1445 if (descent)
1446 *descent = descent2;
1447 if (externalLeading)
1448 *externalLeading = 0;
af0bb3b1 1449}
4bb6408c 1450
7b65ea1a 1451wxCoord wxWindowDC::GetCharWidth() const
4bb6408c 1452{
af0bb3b1
VZ
1453 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1454 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1455
2d120f83 1456 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
af0bb3b1 1457
2d120f83
JS
1458 int direction, ascent, descent;
1459 XCharStruct overall;
1460 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
16c1f7f3 1461 &descent, &overall);
2d120f83 1462 return XDEV2LOGREL(overall.width);
af0bb3b1 1463}
4bb6408c 1464
7b65ea1a 1465wxCoord wxWindowDC::GetCharHeight() const
4bb6408c 1466{
af0bb3b1
VZ
1467 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1468 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1469
2d120f83 1470 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
af0bb3b1 1471
2d120f83
JS
1472 int direction, ascent, descent;
1473 XCharStruct overall;
1474 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
16c1f7f3 1475 &descent, &overall);
2d120f83
JS
1476 // return XDEV2LOGREL(overall.ascent + overall.descent);
1477 return XDEV2LOGREL(ascent + descent);
af0bb3b1 1478}
4bb6408c 1479
af0bb3b1 1480void wxWindowDC::Clear()
4bb6408c 1481{
af0bb3b1
VZ
1482 wxCHECK_RET( Ok(), "invalid dc" );
1483
2d120f83
JS
1484 int w, h;
1485 if (m_window)
16c1f7f3 1486 {
2d120f83 1487 m_window->GetSize(&w, &h);
af0bb3b1 1488
2d120f83
JS
1489 if (m_window && m_window->GetBackingPixmap())
1490 {
1491 w = m_window->GetPixmapWidth();
1492 h = m_window->GetPixmapHeight();
1493 }
16c1f7f3 1494 }
2d120f83 1495 else
16c1f7f3
JS
1496 {
1497 if (this->IsKindOf(CLASSINFO(wxMemoryDC)))
1498 {
2d120f83
JS
1499 wxMemoryDC* memDC = (wxMemoryDC*) this;
1500 w = memDC->GetBitmap().GetWidth();
1501 h = memDC->GetBitmap().GetHeight();
1502 }
16c1f7f3 1503 else
2d120f83 1504 return;
16c1f7f3 1505 }
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, 0, 0, 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, 0, 0, w, h);
af0bb3b1 1514
2d120f83 1515 m_brush = saveBrush;
af0bb3b1 1516}
4bb6408c 1517
a367b9b3
JS
1518void wxWindowDC::Clear(const wxRect& rect)
1519{
af0bb3b1
VZ
1520 wxCHECK_RET( Ok(), "invalid dc" );
1521
2d120f83
JS
1522 int x = rect.x; int y = rect.y;
1523 int w = rect.width; int h = rect.height;
af0bb3b1 1524
2d120f83
JS
1525 wxBrush saveBrush = m_brush;
1526 SetBrush (m_backgroundBrush);
af0bb3b1 1527
2d120f83 1528 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
af0bb3b1 1529
2d120f83
JS
1530 if (m_window && m_window->GetBackingPixmap())
1531 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
af0bb3b1 1532
2d120f83 1533 m_brush = saveBrush;
af0bb3b1 1534}
a367b9b3 1535
dfc54541 1536void wxWindowDC::SetFont( const wxFont &font )
4bb6408c 1537{
af0bb3b1
VZ
1538 wxCHECK_RET( Ok(), "invalid dc" );
1539
2d120f83 1540 m_font = font;
af0bb3b1 1541
2d120f83 1542 if (!m_font.Ok())
e97f20a0 1543 {
7b65ea1a 1544 if ((m_oldFont != (WXFont) 0) && ((wxCoord) m_oldFont != -1))
2d120f83
JS
1545 {
1546 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
af0bb3b1 1547
2d120f83
JS
1548 if (m_window && m_window->GetBackingPixmap())
1549 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1550 }
1551 return;
e97f20a0 1552 }
af0bb3b1 1553
2d120f83 1554 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
af0bb3b1 1555
2d120f83
JS
1556 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1557 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
af0bb3b1 1558
2d120f83
JS
1559 if (m_window && m_window->GetBackingPixmap())
1560 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
af0bb3b1 1561}
4bb6408c 1562
395539f9
MB
1563void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel)
1564{
1565 if (m_logicalFunction == wxXOR)
1566 {
1567 XGCValues values;
1568 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1569 XSetForeground ((Display*) m_display, (GC) m_gc,
1570 pixel ^ values.background);
1571 if (m_window && m_window->GetBackingPixmap())
1572 XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1573 pixel ^ values.background);
1574 }
1575 else
1576 {
1577 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1578 if (m_window && m_window->GetBackingPixmap())
1579 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1580 }
1581}
1582
1583int wxWindowDC::CalculatePixel(wxColour& colour, wxColour& curCol,
1584 bool roundToWhite) const
1585{
1586 const unsigned char wp = (unsigned char)255;
1587
1588 int pixel = -1;
1589 if(!m_colour) // Mono display
1590 {
1591 unsigned char red = colour.Red ();
1592 unsigned char blue = colour.Blue ();
1593 unsigned char green = colour.Green ();
1594 // white
1595 if((red == wp && blue == wp && green == wp) ||
1596 // not black and roundToWhite was specified
1597 ((red != 0 || blue != 0 || green != 0) && roundToWhite))
1598 {
1599 curCol = *wxWHITE;
1600 pixel = (int)WhitePixel((Display*) m_display,
1601 DefaultScreen((Display*) m_display));
1602 curCol.SetPixel(pixel);
1603 colour.SetPixel(pixel);
1604 }
1605 else
1606 {
1607 curCol = *wxBLACK;
1608 pixel = (int)BlackPixel((Display*) m_display,
1609 DefaultScreen((Display*) m_display));
1610 curCol.SetPixel(pixel);
1611 colour.SetPixel(pixel);
1612 }
1613 }
1614 else
1615 {
1616 curCol = colour;
1617 pixel = colour.AllocColour((Display*) m_display);
1618 curCol.SetPixel(pixel);
1619 }
1620
1621 return pixel;
1622}
1623
dfc54541 1624void wxWindowDC::SetPen( const wxPen &pen )
4bb6408c 1625{
af0bb3b1
VZ
1626 wxCHECK_RET( Ok(), "invalid dc" );
1627
2d120f83
JS
1628 m_pen = pen;
1629 if (!m_pen.Ok())
1630 return;
af0bb3b1 1631
2d120f83
JS
1632 wxBitmap oldStipple = m_currentStipple;
1633 int oldStyle = m_currentStyle;
1634 int oldFill = m_currentFill;
1635 int old_pen_width = m_currentPenWidth;
1636 int old_pen_join = m_currentPenJoin;
1637 int old_pen_cap = m_currentPenCap;
1638 int old_pen_nb_dash = m_currentPenDashCount;
69c44812 1639 wxX11Dash *old_pen_dash = m_currentPenDash;
af0bb3b1 1640
2d120f83
JS
1641 wxColour oldPenColour = m_currentColour;
1642 m_currentColour = m_pen.GetColour ();
1643 m_currentStyle = m_pen.GetStyle ();
1644 m_currentFill = m_pen.GetStyle (); // TODO?
1645 m_currentPenWidth = m_pen.GetWidth ();
1646 m_currentPenJoin = m_pen.GetJoin ();
1647 m_currentPenCap = m_pen.GetCap ();
1648 m_currentPenDashCount = m_pen.GetDashCount();
69c44812 1649 m_currentPenDash = (wxX11Dash*)m_pen.GetDash();
af0bb3b1 1650
2d120f83
JS
1651 if (m_currentStyle == wxSTIPPLE)
1652 m_currentStipple = * m_pen.GetStipple ();
af0bb3b1 1653
2d120f83
JS
1654 bool sameStyle = (oldStyle == m_currentStyle &&
1655 oldFill == m_currentFill &&
1656 old_pen_join == m_currentPenJoin &&
1657 old_pen_cap == m_currentPenCap &&
1658 old_pen_nb_dash == m_currentPenDashCount &&
1659 old_pen_dash == m_currentPenDash &&
1660 old_pen_width == m_currentPenWidth);
af0bb3b1 1661
2d120f83
JS
1662 bool sameColour = (oldPenColour.Ok () &&
1663 (oldPenColour.Red () == m_currentColour.Red ()) &&
1664 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1665 (oldPenColour.Green () == m_currentColour.Green ()) &&
1666 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1667
2d120f83 1668 if (!sameStyle || !GetOptimization())
16c1f7f3 1669 {
2d120f83
JS
1670 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1671 if (scaled_width < 0)
1672 scaled_width = 0;
af0bb3b1 1673
2d120f83
JS
1674 int style;
1675 int join;
1676 int cap;
69c44812
MB
1677 static const wxX11Dash dotted[] = {2, 5};
1678 static const wxX11Dash short_dashed[] = {4, 4};
1679 static const wxX11Dash long_dashed[] = {4, 8};
1680 static const wxX11Dash dotted_dashed[] = {6, 6, 2, 6};
af0bb3b1 1681
2d120f83
JS
1682 // We express dash pattern in pen width unit, so we are
1683 // independent of zoom factor and so on...
1684 int req_nb_dash;
69c44812 1685 const wxX11Dash *req_dash;
af0bb3b1 1686
2d120f83
JS
1687 switch (m_pen.GetStyle ())
1688 {
16c1f7f3 1689 case wxUSER_DASH:
2d120f83
JS
1690 req_nb_dash = m_currentPenDashCount;
1691 req_dash = m_currentPenDash;
1692 style = LineOnOffDash;
1693 break;
16c1f7f3 1694 case wxDOT:
2d120f83
JS
1695 req_nb_dash = 2;
1696 req_dash = dotted;
1697 style = LineOnOffDash;
1698 break;
16c1f7f3 1699 case wxSHORT_DASH:
2d120f83
JS
1700 req_nb_dash = 2;
1701 req_dash = short_dashed;
1702 style = LineOnOffDash;
1703 break;
16c1f7f3 1704 case wxLONG_DASH:
2d120f83
JS
1705 req_nb_dash = 2;
1706 req_dash = long_dashed;
1707 style = LineOnOffDash;
1708 break;
16c1f7f3 1709 case wxDOT_DASH:
2d120f83
JS
1710 req_nb_dash = 4;
1711 req_dash = dotted_dashed;
1712 style = LineOnOffDash;
1713 break;
16c1f7f3
JS
1714 case wxSTIPPLE:
1715 case wxSOLID:
1716 case wxTRANSPARENT:
1717 default:
2d120f83 1718 style = LineSolid;
69c44812 1719 req_dash = (wxX11Dash*)NULL;
2d120f83 1720 req_nb_dash = 0;
16c1f7f3 1721 }
af0bb3b1 1722
2d120f83 1723 if (req_dash && req_nb_dash)
16c1f7f3 1724 {
69c44812 1725 wxX11Dash *real_req_dash = new wxX11Dash[req_nb_dash];
2d120f83
JS
1726 if (real_req_dash)
1727 {
1728 int factor = scaled_width == 0 ? 1 : scaled_width;
1729 for (int i = 0; i < req_nb_dash; i++)
1730 real_req_dash[i] = req_dash[i] * factor;
1731 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
af0bb3b1 1732
2d120f83
JS
1733 if (m_window && m_window->GetBackingPixmap())
1734 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1735 delete[]real_req_dash;
1736 }
1737 else
1738 {
1739 // No Memory. We use non-scaled dash pattern...
1740 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
af0bb3b1 1741
2d120f83
JS
1742 if (m_window && m_window->GetBackingPixmap())
1743 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1744 }
16c1f7f3 1745 }
af0bb3b1 1746
2d120f83
JS
1747 switch (m_pen.GetCap ())
1748 {
16c1f7f3 1749 case wxCAP_PROJECTING:
2d120f83
JS
1750 cap = CapProjecting;
1751 break;
16c1f7f3 1752 case wxCAP_BUTT:
2d120f83
JS
1753 cap = CapButt;
1754 break;
16c1f7f3
JS
1755 case wxCAP_ROUND:
1756 default:
2d120f83
JS
1757 cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1758 break;
1759 }
af0bb3b1 1760
2d120f83
JS
1761 switch (m_pen.GetJoin ())
1762 {
16c1f7f3 1763 case wxJOIN_BEVEL:
2d120f83
JS
1764 join = JoinBevel;
1765 break;
16c1f7f3 1766 case wxJOIN_MITER:
2d120f83
JS
1767 join = JoinMiter;
1768 break;
16c1f7f3
JS
1769 case wxJOIN_ROUND:
1770 default:
2d120f83
JS
1771 join = JoinRound;
1772 break;
1773 }
af0bb3b1 1774
2d120f83 1775 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
af0bb3b1 1776
2d120f83
JS
1777 if (m_window && m_window->GetBackingPixmap())
1778 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
16c1f7f3 1779 }
af0bb3b1 1780
16c1f7f3
JS
1781 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1782 {
2d120f83 1783 Pixmap myStipple;
af0bb3b1 1784
2d120f83 1785 oldStipple = wxNullBitmap; // For later reset!!
af0bb3b1 1786
2d120f83
JS
1787 switch (m_currentFill)
1788 {
16c1f7f3 1789 case wxBDIAGONAL_HATCH:
2d120f83
JS
1790 if (bdiag == (Pixmap) 0)
1791 bdiag = XCreateBitmapFromData ((Display*) m_display,
1792 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1793 bdiag_bits, bdiag_width, bdiag_height);
1794 myStipple = bdiag;
1795 break;
16c1f7f3 1796 case wxFDIAGONAL_HATCH:
2d120f83
JS
1797 if (fdiag == (Pixmap) 0)
1798 fdiag = XCreateBitmapFromData ((Display*) m_display,
1799 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1800 fdiag_bits, fdiag_width, fdiag_height);
1801 myStipple = fdiag;
1802 break;
16c1f7f3 1803 case wxCROSS_HATCH:
2d120f83
JS
1804 if (cross == (Pixmap) 0)
1805 cross = XCreateBitmapFromData ((Display*) m_display,
1806 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1807 cross_bits, cross_width, cross_height);
1808 myStipple = cross;
1809 break;
16c1f7f3 1810 case wxHORIZONTAL_HATCH:
2d120f83
JS
1811 if (horiz == (Pixmap) 0)
1812 horiz = XCreateBitmapFromData ((Display*) m_display,
1813 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1814 horiz_bits, horiz_width, horiz_height);
1815 myStipple = horiz;
1816 break;
16c1f7f3 1817 case wxVERTICAL_HATCH:
2d120f83
JS
1818 if (verti == (Pixmap) 0)
1819 verti = XCreateBitmapFromData ((Display*) m_display,
1820 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1821 verti_bits, verti_width, verti_height);
1822 myStipple = verti;
1823 break;
16c1f7f3
JS
1824 case wxCROSSDIAG_HATCH:
1825 default:
2d120f83
JS
1826 if (cdiag == (Pixmap) 0)
1827 cdiag = XCreateBitmapFromData ((Display*) m_display,
1828 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1829 cdiag_bits, cdiag_width, cdiag_height);
1830 myStipple = cdiag;
1831 break;
1832 }
1833 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
af0bb3b1 1834
2d120f83
JS
1835 if (m_window && m_window->GetBackingPixmap())
1836 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
16c1f7f3
JS
1837 }
1838 else if (m_currentStipple.Ok()
2d120f83 1839 && ((m_currentStipple != oldStipple) || !GetOptimization()))
16c1f7f3 1840 {
2d120f83 1841 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
af0bb3b1 1842
2d120f83
JS
1843 if (m_window && m_window->GetBackingPixmap())
1844 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
16c1f7f3 1845 }
af0bb3b1 1846
16c1f7f3
JS
1847 if ((m_currentFill != oldFill) || !GetOptimization())
1848 {
2d120f83 1849 int fill_style;
af0bb3b1 1850
2d120f83
JS
1851 if (m_currentFill == wxSTIPPLE)
1852 fill_style = FillStippled;
1853 else if (IS_HATCH (m_currentFill))
1854 fill_style = FillStippled;
1855 else
1856 fill_style = FillSolid;
1857 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1858 if (m_window && m_window->GetBackingPixmap())
1859 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
16c1f7f3 1860 }
af0bb3b1 1861
16c1f7f3
JS
1862 // must test m_logicalFunction, because it involves background!
1863 if (!sameColour || !GetOptimization()
2d120f83 1864 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
16c1f7f3 1865 {
2d120f83
JS
1866 int pixel = -1;
1867 if (m_pen.GetStyle () == wxTRANSPARENT)
1868 pixel = m_backgroundPixel;
16c1f7f3
JS
1869 else
1870 {
395539f9 1871 pixel = CalculatePixel(m_pen.GetColour(), m_currentColour, FALSE);
16c1f7f3 1872 }
af0bb3b1 1873
2d120f83
JS
1874 // Finally, set the GC to the required colour
1875 if (pixel > -1)
395539f9 1876 SetForegroundPixelWithLogicalFunction(pixel);
16c1f7f3 1877 }
2d120f83
JS
1878 else
1879 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
af0bb3b1 1880
2d120f83 1881 m_autoSetting = 0;
af0bb3b1 1882}
4bb6408c 1883
dfc54541 1884void wxWindowDC::SetBrush( const wxBrush &brush )
4bb6408c 1885{
af0bb3b1
VZ
1886 wxCHECK_RET( Ok(), "invalid dc" );
1887
2d120f83 1888 m_brush = brush;
af0bb3b1 1889
2d120f83
JS
1890 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1891 return;
af0bb3b1 1892
2d120f83
JS
1893 int oldFill = m_currentFill;
1894 wxBitmap oldStipple = m_currentStipple;
af0bb3b1 1895
2d120f83 1896 m_autoSetting |= 0x1;
af0bb3b1 1897
2d120f83
JS
1898 m_currentFill = m_brush.GetStyle ();
1899 if (m_currentFill == wxSTIPPLE)
1900 m_currentStipple = * m_brush.GetStipple ();
af0bb3b1 1901
2d120f83
JS
1902 wxColour oldBrushColour(m_currentColour);
1903 m_currentColour = m_brush.GetColour ();
af0bb3b1 1904
2d120f83
JS
1905 bool sameColour = (oldBrushColour.Ok () &&
1906 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1907 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1908 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1909 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
af0bb3b1 1910
2b830c41
MB
1911 int stippleDepth = -1;
1912
2d120f83
JS
1913 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1914 {
1915 switch (brush.GetStyle ())
1916 {
16c1f7f3 1917 case wxTRANSPARENT:
2d120f83 1918 break;
2b830c41
MB
1919 case wxSTIPPLE:
1920 stippleDepth = m_currentStipple.GetDepth();
1921 // fall through!
16c1f7f3
JS
1922 case wxBDIAGONAL_HATCH:
1923 case wxCROSSDIAG_HATCH:
1924 case wxFDIAGONAL_HATCH:
1925 case wxCROSS_HATCH:
1926 case wxHORIZONTAL_HATCH:
1927 case wxVERTICAL_HATCH:
2d120f83 1928 {
2b830c41
MB
1929 if (stippleDepth == -1) stippleDepth = 1;
1930
1931 // Chris Breeze 23/07/97: use background mode to
1932 // determine whether fill style should be solid or
1933 // transparent
1934 int style = stippleDepth == 1 ?
1935 (m_backgroundMode == wxSOLID ?
1936 FillOpaqueStippled : FillStippled) :
1937 FillTiled;
2d120f83
JS
1938 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1939 if (m_window && m_window->GetBackingPixmap())
1940 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1941 }
1942 break;
16c1f7f3
JS
1943 case wxSOLID:
1944 default:
2d120f83
JS
1945 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1946 if (m_window && m_window->GetBackingPixmap())
2b830c41
MB
1947 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking,
1948 FillSolid);
2d120f83
JS
1949 }
1950 }
af0bb3b1 1951
2d120f83 1952 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
16c1f7f3 1953 {
2d120f83 1954 Pixmap myStipple;
af0bb3b1 1955
2d120f83
JS
1956 switch (m_currentFill)
1957 {
16c1f7f3 1958 case wxBDIAGONAL_HATCH:
2d120f83
JS
1959 if (bdiag == (Pixmap) 0)
1960 bdiag = XCreateBitmapFromData ((Display*) m_display,
1961 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1962 bdiag_bits, bdiag_width, bdiag_height);
1963 myStipple = bdiag;
1964 break;
16c1f7f3 1965 case wxFDIAGONAL_HATCH:
2d120f83
JS
1966 if (fdiag == (Pixmap) 0)
1967 fdiag = XCreateBitmapFromData ((Display*) m_display,
1968 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1969 fdiag_bits, fdiag_width, fdiag_height);
1970 myStipple = fdiag;
1971 break;
16c1f7f3 1972 case wxCROSS_HATCH:
2d120f83
JS
1973 if (cross == (Pixmap) 0)
1974 cross = XCreateBitmapFromData ((Display*) m_display,
1975 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1976 cross_bits, cross_width, cross_height);
1977 myStipple = cross;
1978 break;
16c1f7f3 1979 case wxHORIZONTAL_HATCH:
2d120f83
JS
1980 if (horiz == (Pixmap) 0)
1981 horiz = XCreateBitmapFromData ((Display*) m_display,
1982 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1983 horiz_bits, horiz_width, horiz_height);
1984 myStipple = horiz;
1985 break;
16c1f7f3 1986 case wxVERTICAL_HATCH:
2d120f83
JS
1987 if (verti == (Pixmap) 0)
1988 verti = XCreateBitmapFromData ((Display*) m_display,
1989 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1990 verti_bits, verti_width, verti_height);
1991 myStipple = verti;
1992 break;
16c1f7f3
JS
1993 case wxCROSSDIAG_HATCH:
1994 default:
2d120f83
JS
1995 if (cdiag == (Pixmap) 0)
1996 cdiag = XCreateBitmapFromData ((Display*) m_display,
1997 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1998 cdiag_bits, cdiag_width, cdiag_height);
1999 myStipple = cdiag;
2000 break;
2001 }
2002 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
af0bb3b1 2003
2d120f83
JS
2004 if (m_window && m_window->GetBackingPixmap())
2005 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
16c1f7f3
JS
2006 }
2007 // X can forget the stipple value when resizing a window (apparently)
2008 // so always set the stipple.
2b830c41
MB
2009 else if (m_currentFill != wxSOLID && m_currentFill != wxTRANSPARENT &&
2010 m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
16c1f7f3 2011 {
2b830c41
MB
2012 if (m_currentStipple.GetDepth() == 1)
2013 {
2014 XSetStipple ((Display*) m_display, (GC) m_gc,
2015 (Pixmap) m_currentStipple.GetPixmap());
2d120f83 2016 if (m_window && m_window->GetBackingPixmap())
2b830c41
MB
2017 XSetStipple ((Display*) m_display,(GC) m_gcBacking,
2018 (Pixmap) m_currentStipple.GetPixmap());
2019 }
2020 else
2021 {
2022 XSetTile ((Display*) m_display, (GC) m_gc,
2023 (Pixmap) m_currentStipple.GetPixmap());
2024 if (m_window && m_window->GetBackingPixmap())
2025 XSetTile ((Display*) m_display,(GC) m_gcBacking,
2026 (Pixmap) m_currentStipple.GetPixmap());
2027 }
16c1f7f3 2028 }
af0bb3b1 2029
16c1f7f3
JS
2030 // must test m_logicalFunction, because it involves background!
2031 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
2032 {
395539f9
MB
2033 int pixel = CalculatePixel(m_brush.GetColour(), m_currentColour, TRUE);
2034
2d120f83 2035 if (pixel > -1)
395539f9 2036 SetForegroundPixelWithLogicalFunction(pixel);
16c1f7f3 2037 }
2d120f83
JS
2038 else
2039 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
af0bb3b1 2040}
4bb6408c 2041
dfc54541 2042void wxWindowDC::SetBackground( const wxBrush &brush )
4bb6408c 2043{
af0bb3b1
VZ
2044 wxCHECK_RET( Ok(), "invalid dc" );
2045
2d120f83 2046 m_backgroundBrush = brush;
af0bb3b1 2047
2d120f83
JS
2048 if (!m_backgroundBrush.Ok())
2049 return;
af0bb3b1 2050
395539f9 2051 m_backgroundPixel = m_backgroundBrush.GetColour().AllocColour(m_display);
a91b47e8
JS
2052
2053 // New behaviour, 10/2/99: setting the background brush of a DC
2054 // doesn't affect the window background colour.
2055/*
2d120f83
JS
2056 // XSetWindowBackground doesn't work for non-Window pixmaps
2057 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2058 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
a91b47e8 2059*/
af0bb3b1 2060
2d120f83
JS
2061 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2062 // And Blit,... (Any fct that use XCopyPlane, in fact.)
395539f9 2063 XSetBackground ((Display*) m_display, (GC) m_gc, m_backgroundPixel);
2d120f83 2064 if (m_window && m_window->GetBackingPixmap())
395539f9
MB
2065 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
2066 m_backgroundPixel);
af0bb3b1 2067}
4bb6408c 2068
dfc54541 2069void wxWindowDC::SetLogicalFunction( int function )
4bb6408c 2070{
af0bb3b1
VZ
2071 wxCHECK_RET( Ok(), "invalid dc" );
2072
2d120f83 2073 int x_function;
af0bb3b1 2074
2d120f83
JS
2075 /* MATTHEW: [9] */
2076 if (m_logicalFunction == function)
2077 return;
af0bb3b1 2078
2d120f83 2079 switch (function)
16c1f7f3
JS
2080 {
2081 case wxCLEAR:
2d120f83
JS
2082 x_function = GXclear;
2083 break;
16c1f7f3 2084 case wxXOR:
2d120f83
JS
2085 x_function = GXxor;
2086 break;
16c1f7f3 2087 case wxINVERT:
2d120f83
JS
2088 x_function = GXinvert;
2089 break;
16c1f7f3 2090 case wxOR_REVERSE:
2d120f83
JS
2091 x_function = GXorReverse;
2092 break;
16c1f7f3 2093 case wxAND_REVERSE:
2d120f83
JS
2094 x_function = GXandReverse;
2095 break;
16c1f7f3 2096 case wxAND:
2d120f83
JS
2097 x_function = GXand;
2098 break;
16c1f7f3 2099 case wxOR:
2d120f83
JS
2100 x_function = GXor;
2101 break;
16c1f7f3 2102 case wxAND_INVERT:
2d120f83
JS
2103 x_function = GXandInverted;
2104 break;
16c1f7f3 2105 case wxNO_OP:
2d120f83
JS
2106 x_function = GXnoop;
2107 break;
16c1f7f3 2108 case wxNOR:
2d120f83
JS
2109 x_function = GXnor;
2110 break;
16c1f7f3 2111 case wxEQUIV:
2d120f83
JS
2112 x_function = GXequiv;
2113 break;
16c1f7f3 2114 case wxSRC_INVERT:
2d120f83
JS
2115 x_function = GXcopyInverted;
2116 break;
16c1f7f3 2117 case wxOR_INVERT:
2d120f83
JS
2118 x_function = GXorInverted;
2119 break;
16c1f7f3 2120 case wxNAND:
2d120f83
JS
2121 x_function = GXnand;
2122 break;
16c1f7f3 2123 case wxSET:
2d120f83
JS
2124 x_function = GXset;
2125 break;
16c1f7f3
JS
2126 case wxCOPY:
2127 default:
2d120f83
JS
2128 x_function = GXcopy;
2129 break;
16c1f7f3 2130 }
af0bb3b1 2131
2d120f83
JS
2132 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
2133 if (m_window && m_window->GetBackingPixmap())
2134 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
af0bb3b1 2135
2d120f83
JS
2136 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
2137 /* MATTHEW: [9] Need to redo pen simply */
2138 m_autoSetting |= 0x2;
af0bb3b1 2139
2d120f83 2140 m_logicalFunction = function;
af0bb3b1
VZ
2141
2142}
4bb6408c 2143
dfc54541 2144void wxWindowDC::SetTextForeground( const wxColour &col )
4bb6408c 2145{
af0bb3b1
VZ
2146 wxCHECK_RET( Ok(), "invalid dc" );
2147
2148 if (m_textForegroundColour == col)
2149 return;
2150
2d120f83 2151 m_textForegroundColour = col;
af0bb3b1
VZ
2152
2153}
4bb6408c 2154
dfc54541 2155void wxWindowDC::SetTextBackground( const wxColour &col )
4bb6408c 2156{
af0bb3b1
VZ
2157 wxCHECK_RET( Ok(), "invalid dc" );
2158
2159 if (m_textBackgroundColour == col)
2160 return;
2161
2d120f83 2162 m_textBackgroundColour = col;
af0bb3b1
VZ
2163 if (!m_textBackgroundColour.Ok())
2164 return;
2165}
4bb6408c 2166
dfc54541 2167void wxWindowDC::SetBackgroundMode( int mode )
4bb6408c 2168{
2d120f83 2169 m_backgroundMode = mode;
af0bb3b1 2170}
16c1f7f3
JS
2171
2172void wxWindowDC::SetPalette( const wxPalette& palette )
2173{
2d120f83
JS
2174 if (m_window)
2175 {
2176 if (palette.Ok())
2177 /* Use GetXColormap */
2178 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2179 (Colormap) palette.GetXColormap());
2180 else
2181 /* Use wxGetMainColormap */
2182 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2183 (Colormap) wxTheApp->GetMainColormap(m_display));
2184 }
af0bb3b1 2185}
4bb6408c 2186
16c1f7f3 2187// Helper function
af0bb3b1 2188void wxWindowDC::SetDCClipping()
4bb6408c 2189{
2d120f83 2190 // m_userRegion is the region set by calling SetClippingRegion
af0bb3b1 2191
2d120f83
JS
2192 if (m_currentRegion)
2193 XDestroyRegion ((Region) m_currentRegion);
af0bb3b1 2194
2d120f83
JS
2195 // We need to take into account
2196 // clipping imposed on a window by a repaint.
2197 // We'll combine it with the user region. But for now,
2198 // just use the currently-defined user clipping region.
2199 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
2200 m_currentRegion = (WXRegion) XCreateRegion ();
2201 else
2202 m_currentRegion = (WXRegion) NULL;
af0bb3b1 2203
2d120f83
JS
2204 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2205 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
2206 else if (m_userRegion)
2207 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
2208 else if (m_window && m_window->GetUpdateRegion().Ok())
af0bb3b1 2209 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
2d120f83 2210 (Region) m_currentRegion);
af0bb3b1 2211
2d120f83 2212 if (m_currentRegion)
16c1f7f3 2213 {
2d120f83 2214 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
16c1f7f3 2215 }
2d120f83 2216 else
16c1f7f3 2217 {
2d120f83 2218 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
16c1f7f3 2219 }
af0bb3b1 2220
16c1f7f3 2221}
4bb6408c 2222
7b65ea1a 2223void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
4bb6408c 2224{
33caefb3 2225 wxDC::DoSetClippingRegion( x, y, width, height );
af0bb3b1 2226
2d120f83
JS
2227 if (m_userRegion)
2228 XDestroyRegion ((Region) m_userRegion);
2229 m_userRegion = (WXRegion) XCreateRegion ();
2230 XRectangle r;
2231 r.x = XLOG2DEV (x);
2232 r.y = YLOG2DEV (y);
2233 r.width = XLOG2DEVREL(width);
2234 r.height = YLOG2DEVREL(height);
2235 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
af0bb3b1 2236
2d120f83 2237 SetDCClipping ();
af0bb3b1 2238
2d120f83
JS
2239 // Needs to work differently for Pixmap: without this,
2240 // there's a nasty (Display*) m_display bug. 8/12/94
2241 if (m_window && m_window->GetBackingPixmap())
2242 {
2243 XRectangle rects[1];
af0bb3b1 2244 rects[0].x = XLOG2DEV_2(x);
2d120f83
JS
2245 rects[0].y = YLOG2DEV_2(y);
2246 rects[0].width = XLOG2DEVREL(width);
2247 rects[0].height = YLOG2DEVREL(height);
2248 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2249 }
af0bb3b1 2250}
4bb6408c 2251
af0bb3b1 2252void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
a724d789 2253{
2d120f83 2254 wxRect box = region.GetBox();
af0bb3b1 2255
33caefb3 2256 wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height );
af0bb3b1 2257
2d120f83
JS
2258 if (m_userRegion)
2259 XDestroyRegion ((Region) m_userRegion);
2260 m_userRegion = (WXRegion) XCreateRegion ();
af0bb3b1 2261
2d120f83 2262 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
af0bb3b1 2263
2d120f83 2264 SetDCClipping ();
af0bb3b1 2265
2d120f83
JS
2266 // Needs to work differently for Pixmap: without this,
2267 // there's a nasty (Display*) m_display bug. 8/12/94
2268 if (m_window && m_window->GetBackingPixmap())
2269 {
2270 XRectangle rects[1];
2271 rects[0].x = XLOG2DEV_2(box.x);
2272 rects[0].y = YLOG2DEV_2(box.y);
2273 rects[0].width = XLOG2DEVREL(box.width);
2274 rects[0].height = YLOG2DEVREL(box.height);
2275 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2276 }
af0bb3b1 2277}
a724d789
JS
2278
2279
af0bb3b1 2280void wxWindowDC::DestroyClippingRegion()
4bb6408c 2281{
2d120f83 2282 wxDC::DestroyClippingRegion();
af0bb3b1 2283
2d120f83
JS
2284 if (m_userRegion)
2285 XDestroyRegion ((Region) m_userRegion);
2286 m_userRegion = NULL;
af0bb3b1 2287
2d120f83 2288 SetDCClipping ();
af0bb3b1 2289
2d120f83
JS
2290 XGCValues gc_val;
2291 gc_val.clip_mask = None;
2292 if (m_window && m_window->GetBackingPixmap())
2293 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
4bb6408c
JS
2294}
2295
af0bb3b1
VZ
2296// Resolution in pixels per logical inch
2297wxSize wxWindowDC::GetPPI() const
4bb6408c 2298{
af0bb3b1 2299 return wxSize(100, 100);
4bb6408c
JS
2300}
2301
af0bb3b1 2302int wxWindowDC::GetDepth() const
7bcb11d3 2303{
af0bb3b1
VZ
2304 // TODO
2305 return 24;
7bcb11d3
JS
2306}
2307
96f201da
RR
2308
2309
2310
af0bb3b1
VZ
2311// ----------------------------------------------------------------------------
2312// wxPaintDC
2313// ----------------------------------------------------------------------------
55acd85e 2314
af0bb3b1 2315wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win)
55acd85e
JS
2316{
2317 wxRegion* region = NULL;
af0bb3b1 2318
55acd85e 2319 // Combine all the update rects into a region
af0bb3b1
VZ
2320 const wxRectList& updateRects(win->GetUpdateRects());
2321 if ( updateRects.GetCount() != 0 )
55acd85e 2322 {
af0bb3b1
VZ
2323 for ( wxRectList::Node *node = updateRects.GetFirst();
2324 node;
2325 node = node->GetNext() )
55acd85e 2326 {
af0bb3b1
VZ
2327 wxRect* rect = node->GetData();
2328
55acd85e
JS
2329 if (!region)
2330 region = new wxRegion(*rect);
2331 else
2332 // TODO: is this correct? In SetDCClipping above,
2333 // XIntersectRegion is used to combine paint and user
2334 // regions. XIntersectRegion appears to work in that case...
2335 region->Union(*rect);
2336 }
2337 }
2338 else
2339 {
2340 int cw, ch;
2341 win->GetClientSize(&cw, &ch);
2342 region = new wxRegion(wxRect(0, 0, cw, ch));
2343 }
af0bb3b1
VZ
2344
2345 win->SetUpdateRegion(*region);
2346
25f47127
JS
2347 wxRegion& theRegion(win->GetUpdateRegion());
2348 theRegion.SetRects(updateRects); // We also store in terms of rects, for iteration to work.
2349
55acd85e
JS
2350 // Set the clipping region. Any user-defined region will be combined with this
2351 // one in SetDCClipping.
2352 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
af0bb3b1 2353
55acd85e
JS
2354 delete region;
2355}
2356
2357wxPaintDC::~wxPaintDC()
2358{
2359 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2360 if (m_window)
af0bb3b1
VZ
2361 m_window->ClearUpdateRegion();
2362}
2363
2364// ----------------------------------------------------------------------------
2365// private functions
2366// ----------------------------------------------------------------------------
2367
2368/*
2369 Used when copying between drawables on different (Display*) m_displays. Not
2370 very fast, but better than giving up.
2371*/
2372
2373static void XCopyRemote(Display *src_display, Display *dest_display,
2374 Drawable src, Drawable dest,
2375 GC destgc,
2376 int srcx, int srcy,
2377 unsigned int w, unsigned int h,
2378 int destx, int desty,
2379 bool more, XImage **cache)
2380{
2381 XImage *image, *destimage;
2382 Colormap destcm, srccm;
2383 static const int CACHE_SIZE = 256;
2384
2385 unsigned int i, j;
2386 unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2387 int k, cache_pos, all_cache;
2388
2389 if (!cache || !*cache)
2390 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2391 else
2392 image = *cache;
2393
2394 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2395
2396 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2397 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2398
2399 cache_pos = 0;
2400 all_cache = FALSE;
2401
2402 for (i = 0; i < w; i++)
2403 for (j = 0; j < h; j++) {
2404 unsigned long pixel;
2405 XColor xcol;
2406
2407 pixel = XGetPixel(image, i, j);
2408 for (k = cache_pos; k--; )
2409 if (cachesrc[k] == pixel) {
2410 pixel = cachedest[k];
2411 goto install;
2412 }
2413 if (all_cache)
2414 for (k = CACHE_SIZE; k-- > cache_pos; )
2415 if (cachesrc[k] == pixel) {
2416 pixel = cachedest[k];
2417 goto install;
2418 }
2419
2420 cachesrc[cache_pos] = xcol.pixel = pixel;
2421 XQueryColor(src_display, srccm, &xcol);
2422 if (!XAllocColor(dest_display, destcm, &xcol))
2423 xcol.pixel = 0;
2424 cachedest[cache_pos] = pixel = xcol.pixel;
2425
2426 if (++cache_pos >= CACHE_SIZE) {
2427 cache_pos = 0;
2428 all_cache = TRUE;
2429 }
2430
2431install:
2432 XPutPixel(destimage, i, j, pixel);
2433 }
2434
2435 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2436 XDestroyImage(destimage);
2437
2438 if (more)
2439 *cache = image;
2440 else
2441 XDestroyImage(image);
2442}
2443
2444#if 0
2445
2446/* Helper function for 16-bit fonts */
2447static int str16len(const char *s)
2448{
2449 int count = 0;
2450
2451 while (s[0] && s[1]) {
2452 count++;
2453 s += 2;
2454 }
2455
2456 return count;
55acd85e
JS
2457}
2458
af0bb3b1 2459#endif // 0