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