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