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