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