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