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