Fix DrawRotatedtext to behave more like wxMSW: take into account
[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 = (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 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, (char*) (const char*) text, slen, &direction,
1134 &ascent, &descent, &overall_return);
1135
1136 cx = overall_return.width;
1137 cy = ascent + descent;
1138 }
1139
1140 // First draw a rectangle representing the text background, if a text
1141 // background is specified
1142 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1143 {
1144 wxColour oldPenColour = m_currentColour;
1145 m_currentColour = m_textBackgroundColour;
1146 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1147 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1148 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1149 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1150
1151 // This separation of the big && test required for gcc2.7/HP UX 9.02
1152 // or pixel value can be corrupted!
1153 sameColour = (sameColour &&
1154 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1155
1156 if (!sameColour || !GetOptimization())
1157 {
1158 int pixel = m_textBackgroundColour.AllocColour(m_display);
1159 m_currentColour = m_textBackgroundColour;
1160
1161 // Set the GC to the required colour
1162 if (pixel > -1)
1163 {
1164 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1165 if (m_window && m_window->GetBackingPixmap())
1166 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1167 }
1168 }
1169 else
1170 m_textBackgroundColour = oldPenColour ;
1171
1172 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1173 if (m_window && m_window->GetBackingPixmap())
1174 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1175 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1176 }
1177
1178 // Now set the text foreground and draw the text
1179 if (m_textForegroundColour.Ok ())
1180 {
1181 wxColour oldPenColour = m_currentColour;
1182 m_currentColour = m_textForegroundColour;
1183 bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () &&
1184 (oldPenColour.Red () == m_currentColour.Red ()) &&
1185 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1186 (oldPenColour.Green () == m_currentColour.Green ()) &&
1187 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1188
1189 if (!sameColour || !GetOptimization())
1190 {
1191 int pixel = CalculatePixel(m_textForegroundColour,
1192 m_currentColour, FALSE);
1193
1194 // Set the GC to the required colour
1195 if (pixel > -1)
1196 {
1197 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1198 if (m_window && m_window->GetBackingPixmap())
1199 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1200 }
1201 }
1202 else
1203 m_textForegroundColour = oldPenColour;
1204 }
1205
1206 // We need to add the ascent, not the whole height, since X draws at the
1207 // point above the descender.
1208 #if 0
1209 if (use16)
1210 XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
1211 (XChar2b *)(char*) (const char*) text, slen);
1212 else
1213 #endif // 0
1214 XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1215
1216 if (m_window && m_window->GetBackingPixmap()) {
1217 #if 0
1218 if (use16)
1219 XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1220 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1221 (XChar2b *)(char*) (const char*) text, slen);
1222 else
1223 #endif // 0
1224 XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1225 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, (char*) (const char*) text, slen);
1226 }
1227
1228 // restore fill style
1229 XSetFillStyle ((Display*) m_display, (GC) m_gc, gcV.fill_style);
1230 if (m_window && m_window->GetBackingPixmap())
1231 XSetFillStyle ((Display*) m_display, (GC) m_gcBacking,
1232 gcBackingV.fill_style);
1233
1234 wxCoord w, h;
1235 GetTextExtent (text, &w, &h);
1236 CalcBoundingBox (x + w, y + h);
1237 CalcBoundingBox (x, y);
1238 }
1239
1240 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y,
1241 double angle )
1242 {
1243 if (angle == 0.0)
1244 {
1245 DrawText(text, x, y);
1246 return;
1247 }
1248
1249 wxCHECK_RET( Ok(), "invalid dc" );
1250
1251 int oldBackgroundPixel = -1;
1252 int oldForegroundPixel = -1;
1253 int foregroundPixel = -1;
1254 int backgroundPixel = -1;
1255
1256 if (m_textBackgroundColour.Ok())
1257 {
1258 oldBackgroundPixel = m_backgroundPixel;
1259 backgroundPixel = m_textBackgroundColour.AllocColour(m_display);
1260 }
1261 if (m_textForegroundColour.Ok())
1262 {
1263 oldForegroundPixel = m_currentColour.GetPixel();
1264
1265 if( m_textForegroundColour.GetPixel() <= -1 )
1266 CalculatePixel( m_textForegroundColour,
1267 m_textForegroundColour, TRUE);
1268
1269 foregroundPixel = m_textForegroundColour.GetPixel();
1270 }
1271
1272 // Since X draws from the baseline of the text, must add the text height
1273 int cx = 0;
1274 int cy = 0;
1275 int ascent = 0;
1276 int slen = text.length();
1277
1278 if (m_font.Ok())
1279 {
1280 // Calculate text extent.
1281 WXFontStructPtr pFontStruct =
1282 m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1283 int direction, descent;
1284 XCharStruct overall_return;
1285 #if 0
1286 if (use16)
1287 (void)XTextExtents16((XFontStruct*) pFontStruct,
1288 (XChar2b *)(const char*) text,
1289 slen, &direction,
1290 &ascent, &descent, &overall_return);
1291 else
1292 #endif // 0
1293 (void)XTextExtents((XFontStruct*) pFontStruct,
1294 (char*)text.c_str(), slen, &direction,
1295 &ascent, &descent, &overall_return);
1296
1297 cx = overall_return.width;
1298 cy = ascent + descent;
1299 }
1300
1301 wxBitmap src(cx, cy);
1302 wxMemoryDC dc;
1303 dc.SelectObject(src);
1304 dc.SetFont(GetFont());
1305 dc.SetBackground(*wxWHITE_BRUSH);
1306 dc.SetBrush(*wxBLACK_BRUSH);
1307 dc.Clear();
1308 dc.DrawText(text, 0, 0);
1309 dc.SetFont(wxNullFont);
1310
1311 // Calculate the size of the rotated bounding box.
1312 double dx = cos(angle / 180.0 * M_PI);
1313 double dy = sin(angle / 180.0 * M_PI);
1314 double x4 = cy * dy;
1315 double y4 = cy * dx;
1316 double x3 = cx * dx;
1317 double y3 = -cx * dy;
1318 double x2 = x3 + x4;
1319 double y2 = y3 + y4;
1320 double x1 = x;
1321 double y1 = y;
1322
1323 // Create image from the source bitmap after writing the text into it.
1324 wxImage image = src.ConvertToImage();
1325
1326 int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
1327 int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
1328 int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
1329 int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
1330
1331 bool lastFore = false, lastBack = false;
1332
1333 // This rotates counterclockwise around the top left corner.
1334 for (int rx = minx; rx < maxx; rx++)
1335 {
1336 for (int ry = miny; ry < maxy; ry++)
1337 {
1338 // transform dest coords to source coords
1339 int sx = (int) (rx * dx - ry * dy + 0.5);
1340 int sy = - (int) (-ry * dx - rx * dy + 0.5);
1341 if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
1342 {
1343 bool textPixel = image.GetRed(sx, sy) == 0;
1344
1345 if (!textPixel && m_backgroundMode != wxSOLID)
1346 continue;
1347
1348 wxCoord ox = (wxCoord) (x1 + rx),
1349 oy = (wxCoord) (y1 + ry);
1350 // draw black pixels, ignore white ones (i.e. transparent b/g)
1351 if (textPixel && !lastFore)
1352 {
1353 XSetForeground ((Display*) m_display, (GC) m_gc,
1354 foregroundPixel);
1355 lastFore = true;
1356 lastBack = false;
1357 }
1358 else if (!textPixel && !lastBack)
1359 {
1360 XSetForeground ((Display*) m_display, (GC) m_gc,
1361 backgroundPixel);
1362 lastFore = false;
1363 lastBack = true;
1364 }
1365
1366 XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap,
1367 (GC) m_gc, XLOG2DEV (ox), YLOG2DEV (oy));
1368 if (m_window && m_window->GetBackingPixmap())
1369 XDrawPoint ((Display*) m_display,
1370 (Pixmap) m_window->GetBackingPixmap(),
1371 (GC) m_gcBacking,
1372 XLOG2DEV_2 (ox), YLOG2DEV_2 (oy));
1373 }
1374 }
1375 }
1376
1377 if (oldBackgroundPixel > -1)
1378 {
1379 XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
1380 if (m_window && m_window->GetBackingPixmap())
1381 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1382 oldBackgroundPixel);
1383 }
1384 if (oldForegroundPixel > -1)
1385 {
1386 XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1387 if (m_window && m_window->GetBackingPixmap())
1388 XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1389 oldForegroundPixel);
1390 }
1391
1392 CalcBoundingBox (minx, miny);
1393 CalcBoundingBox (maxx, maxy);
1394 }
1395
1396 bool wxWindowDC::CanGetTextExtent() const
1397 {
1398 return TRUE;
1399 }
1400
1401 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1402 wxCoord *descent, wxCoord *externalLeading,
1403 wxFont *font ) const
1404 {
1405 wxCHECK_RET( Ok(), "invalid dc" );
1406
1407 wxFont* theFont = font;
1408 if (!theFont)
1409 theFont = (wxFont *)&m_font; // const_cast
1410
1411 if (!theFont->Ok())
1412 {
1413 // TODO: this should be an error log function
1414 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1415
1416 if (width) *width = -1;
1417 if (height) *height = -1;
1418 return;
1419 }
1420
1421 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1422
1423 int direction, ascent, descent2;
1424 XCharStruct overall;
1425 int slen;
1426
1427 #if 0
1428 if (use16)
1429 slen = str16len(string);
1430 else
1431 #endif // 0
1432 slen = strlen(string);
1433
1434 #if 0
1435 if (use16)
1436 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1437 &ascent, &descent2, &overall);
1438 else
1439 #endif // 0
1440 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1441 &ascent, &descent2, &overall);
1442
1443 if (width) *width = XDEV2LOGREL (overall.width);
1444 if (height) *height = YDEV2LOGREL (ascent + descent2);
1445 if (descent)
1446 *descent = descent2;
1447 if (externalLeading)
1448 *externalLeading = 0;
1449 }
1450
1451 wxCoord wxWindowDC::GetCharWidth() const
1452 {
1453 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1454 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1455
1456 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
1457
1458 int direction, ascent, descent;
1459 XCharStruct overall;
1460 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1461 &descent, &overall);
1462 return XDEV2LOGREL(overall.width);
1463 }
1464
1465 wxCoord wxWindowDC::GetCharHeight() const
1466 {
1467 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1468 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1469
1470 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1471
1472 int direction, ascent, descent;
1473 XCharStruct overall;
1474 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1475 &descent, &overall);
1476 // return XDEV2LOGREL(overall.ascent + overall.descent);
1477 return XDEV2LOGREL(ascent + descent);
1478 }
1479
1480 void wxWindowDC::Clear()
1481 {
1482 wxCHECK_RET( Ok(), "invalid dc" );
1483
1484 int w, h;
1485 if (m_window)
1486 {
1487 m_window->GetSize(&w, &h);
1488
1489 if (m_window && m_window->GetBackingPixmap())
1490 {
1491 w = m_window->GetPixmapWidth();
1492 h = m_window->GetPixmapHeight();
1493 }
1494 }
1495 else
1496 {
1497 if (this->IsKindOf(CLASSINFO(wxMemoryDC)))
1498 {
1499 wxMemoryDC* memDC = (wxMemoryDC*) this;
1500 w = memDC->GetBitmap().GetWidth();
1501 h = memDC->GetBitmap().GetHeight();
1502 }
1503 else
1504 return;
1505 }
1506
1507 wxBrush saveBrush = m_brush;
1508 SetBrush (m_backgroundBrush);
1509
1510 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, 0, w, h);
1511
1512 if (m_window && m_window->GetBackingPixmap())
1513 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 0, 0, w, h);
1514
1515 m_brush = saveBrush;
1516 }
1517
1518 void wxWindowDC::Clear(const wxRect& rect)
1519 {
1520 wxCHECK_RET( Ok(), "invalid dc" );
1521
1522 int x = rect.x; int y = rect.y;
1523 int w = rect.width; int h = rect.height;
1524
1525 wxBrush saveBrush = m_brush;
1526 SetBrush (m_backgroundBrush);
1527
1528 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
1529
1530 if (m_window && m_window->GetBackingPixmap())
1531 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
1532
1533 m_brush = saveBrush;
1534 }
1535
1536 void wxWindowDC::SetFont( const wxFont &font )
1537 {
1538 wxCHECK_RET( Ok(), "invalid dc" );
1539
1540 m_font = font;
1541
1542 if (!m_font.Ok())
1543 {
1544 if ((m_oldFont != (WXFont) 0) && ((wxCoord) m_oldFont != -1))
1545 {
1546 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
1547
1548 if (m_window && m_window->GetBackingPixmap())
1549 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1550 }
1551 return;
1552 }
1553
1554 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1555
1556 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1557 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1558
1559 if (m_window && m_window->GetBackingPixmap())
1560 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
1561 }
1562
1563 void wxWindowDC::SetForegroundPixelWithLogicalFunction(int pixel)
1564 {
1565 if (m_logicalFunction == wxXOR)
1566 {
1567 XGCValues values;
1568 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1569 XSetForeground ((Display*) m_display, (GC) m_gc,
1570 pixel ^ values.background);
1571 if (m_window && m_window->GetBackingPixmap())
1572 XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1573 pixel ^ values.background);
1574 }
1575 else
1576 {
1577 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1578 if (m_window && m_window->GetBackingPixmap())
1579 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1580 }
1581 }
1582
1583 int wxWindowDC::CalculatePixel(wxColour& colour, wxColour& curCol,
1584 bool roundToWhite) const
1585 {
1586 const unsigned char wp = (unsigned char)255;
1587
1588 int pixel = -1;
1589 if(!m_colour) // Mono display
1590 {
1591 unsigned char red = colour.Red ();
1592 unsigned char blue = colour.Blue ();
1593 unsigned char green = colour.Green ();
1594 // white
1595 if((red == wp && blue == wp && green == wp) ||
1596 // not black and roundToWhite was specified
1597 ((red != 0 || blue != 0 || green != 0) && roundToWhite))
1598 {
1599 curCol = *wxWHITE;
1600 pixel = (int)WhitePixel((Display*) m_display,
1601 DefaultScreen((Display*) m_display));
1602 curCol.SetPixel(pixel);
1603 colour.SetPixel(pixel);
1604 }
1605 else
1606 {
1607 curCol = *wxBLACK;
1608 pixel = (int)BlackPixel((Display*) m_display,
1609 DefaultScreen((Display*) m_display));
1610 curCol.SetPixel(pixel);
1611 colour.SetPixel(pixel);
1612 }
1613 }
1614 else
1615 {
1616 curCol = colour;
1617 pixel = colour.AllocColour((Display*) m_display);
1618 curCol.SetPixel(pixel);
1619 }
1620
1621 return pixel;
1622 }
1623
1624 void wxWindowDC::SetPen( const wxPen &pen )
1625 {
1626 wxCHECK_RET( Ok(), "invalid dc" );
1627
1628 m_pen = pen;
1629 if (!m_pen.Ok())
1630 return;
1631
1632 wxBitmap oldStipple = m_currentStipple;
1633 int oldStyle = m_currentStyle;
1634 int oldFill = m_currentFill;
1635 int old_pen_width = m_currentPenWidth;
1636 int old_pen_join = m_currentPenJoin;
1637 int old_pen_cap = m_currentPenCap;
1638 int old_pen_nb_dash = m_currentPenDashCount;
1639 wxMOTIFDash *old_pen_dash = m_currentPenDash;
1640
1641 wxColour oldPenColour = m_currentColour;
1642 m_currentColour = m_pen.GetColour ();
1643 m_currentStyle = m_pen.GetStyle ();
1644 m_currentFill = m_pen.GetStyle (); // TODO?
1645 m_currentPenWidth = m_pen.GetWidth ();
1646 m_currentPenJoin = m_pen.GetJoin ();
1647 m_currentPenCap = m_pen.GetCap ();
1648 m_currentPenDashCount = m_pen.GetDashCount();
1649 m_currentPenDash = (wxMOTIFDash*)m_pen.GetDash();
1650
1651 if (m_currentStyle == wxSTIPPLE)
1652 m_currentStipple = * m_pen.GetStipple ();
1653
1654 bool sameStyle = (oldStyle == m_currentStyle &&
1655 oldFill == m_currentFill &&
1656 old_pen_join == m_currentPenJoin &&
1657 old_pen_cap == m_currentPenCap &&
1658 old_pen_nb_dash == m_currentPenDashCount &&
1659 old_pen_dash == m_currentPenDash &&
1660 old_pen_width == m_currentPenWidth);
1661
1662 bool sameColour = (oldPenColour.Ok () &&
1663 (oldPenColour.Red () == m_currentColour.Red ()) &&
1664 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1665 (oldPenColour.Green () == m_currentColour.Green ()) &&
1666 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1667
1668 if (!sameStyle || !GetOptimization())
1669 {
1670 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1671 if (scaled_width < 0)
1672 scaled_width = 0;
1673
1674 int style;
1675 int join;
1676 int cap;
1677 static const wxMOTIFDash dotted[] = {2, 5};
1678 static const wxMOTIFDash short_dashed[] = {4, 4};
1679 static const wxMOTIFDash long_dashed[] = {4, 8};
1680 static const wxMOTIFDash dotted_dashed[] = {6, 6, 2, 6};
1681
1682 // We express dash pattern in pen width unit, so we are
1683 // independent of zoom factor and so on...
1684 int req_nb_dash;
1685 const wxMOTIFDash *req_dash;
1686
1687 switch (m_pen.GetStyle ())
1688 {
1689 case wxUSER_DASH:
1690 req_nb_dash = m_currentPenDashCount;
1691 req_dash = m_currentPenDash;
1692 style = LineOnOffDash;
1693 break;
1694 case wxDOT:
1695 req_nb_dash = 2;
1696 req_dash = dotted;
1697 style = LineOnOffDash;
1698 break;
1699 case wxSHORT_DASH:
1700 req_nb_dash = 2;
1701 req_dash = short_dashed;
1702 style = LineOnOffDash;
1703 break;
1704 case wxLONG_DASH:
1705 req_nb_dash = 2;
1706 req_dash = long_dashed;
1707 style = LineOnOffDash;
1708 break;
1709 case wxDOT_DASH:
1710 req_nb_dash = 4;
1711 req_dash = dotted_dashed;
1712 style = LineOnOffDash;
1713 break;
1714 case wxSTIPPLE:
1715 case wxSOLID:
1716 case wxTRANSPARENT:
1717 default:
1718 style = LineSolid;
1719 req_dash = (wxMOTIFDash*)NULL;
1720 req_nb_dash = 0;
1721 }
1722
1723 if (req_dash && req_nb_dash)
1724 {
1725 wxMOTIFDash *real_req_dash = new wxMOTIFDash[req_nb_dash];
1726 if (real_req_dash)
1727 {
1728 int factor = scaled_width == 0 ? 1 : scaled_width;
1729 for (int i = 0; i < req_nb_dash; i++)
1730 real_req_dash[i] = req_dash[i] * factor;
1731 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1732
1733 if (m_window && m_window->GetBackingPixmap())
1734 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1735 delete[]real_req_dash;
1736 }
1737 else
1738 {
1739 // No Memory. We use non-scaled dash pattern...
1740 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1741
1742 if (m_window && m_window->GetBackingPixmap())
1743 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1744 }
1745 }
1746
1747 switch (m_pen.GetCap ())
1748 {
1749 case wxCAP_PROJECTING:
1750 cap = CapProjecting;
1751 break;
1752 case wxCAP_BUTT:
1753 cap = CapButt;
1754 break;
1755 case wxCAP_ROUND:
1756 default:
1757 cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1758 break;
1759 }
1760
1761 switch (m_pen.GetJoin ())
1762 {
1763 case wxJOIN_BEVEL:
1764 join = JoinBevel;
1765 break;
1766 case wxJOIN_MITER:
1767 join = JoinMiter;
1768 break;
1769 case wxJOIN_ROUND:
1770 default:
1771 join = JoinRound;
1772 break;
1773 }
1774
1775 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1776
1777 if (m_window && m_window->GetBackingPixmap())
1778 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1779 }
1780
1781 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1782 {
1783 Pixmap myStipple;
1784
1785 oldStipple = wxNullBitmap; // For later reset!!
1786
1787 switch (m_currentFill)
1788 {
1789 case wxBDIAGONAL_HATCH:
1790 if (bdiag == (Pixmap) 0)
1791 bdiag = XCreateBitmapFromData ((Display*) m_display,
1792 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1793 bdiag_bits, bdiag_width, bdiag_height);
1794 myStipple = bdiag;
1795 break;
1796 case wxFDIAGONAL_HATCH:
1797 if (fdiag == (Pixmap) 0)
1798 fdiag = XCreateBitmapFromData ((Display*) m_display,
1799 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1800 fdiag_bits, fdiag_width, fdiag_height);
1801 myStipple = fdiag;
1802 break;
1803 case wxCROSS_HATCH:
1804 if (cross == (Pixmap) 0)
1805 cross = XCreateBitmapFromData ((Display*) m_display,
1806 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1807 cross_bits, cross_width, cross_height);
1808 myStipple = cross;
1809 break;
1810 case wxHORIZONTAL_HATCH:
1811 if (horiz == (Pixmap) 0)
1812 horiz = XCreateBitmapFromData ((Display*) m_display,
1813 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1814 horiz_bits, horiz_width, horiz_height);
1815 myStipple = horiz;
1816 break;
1817 case wxVERTICAL_HATCH:
1818 if (verti == (Pixmap) 0)
1819 verti = XCreateBitmapFromData ((Display*) m_display,
1820 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1821 verti_bits, verti_width, verti_height);
1822 myStipple = verti;
1823 break;
1824 case wxCROSSDIAG_HATCH:
1825 default:
1826 if (cdiag == (Pixmap) 0)
1827 cdiag = XCreateBitmapFromData ((Display*) m_display,
1828 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1829 cdiag_bits, cdiag_width, cdiag_height);
1830 myStipple = cdiag;
1831 break;
1832 }
1833 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1834
1835 if (m_window && m_window->GetBackingPixmap())
1836 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1837 }
1838 else if (m_currentStipple.Ok()
1839 && ((m_currentStipple != oldStipple) || !GetOptimization()))
1840 {
1841 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1842
1843 if (m_window && m_window->GetBackingPixmap())
1844 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1845 }
1846
1847 if ((m_currentFill != oldFill) || !GetOptimization())
1848 {
1849 int fill_style;
1850
1851 if (m_currentFill == wxSTIPPLE)
1852 fill_style = FillStippled;
1853 else if (IS_HATCH (m_currentFill))
1854 fill_style = FillStippled;
1855 else
1856 fill_style = FillSolid;
1857 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1858 if (m_window && m_window->GetBackingPixmap())
1859 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1860 }
1861
1862 // must test m_logicalFunction, because it involves background!
1863 if (!sameColour || !GetOptimization()
1864 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1865 {
1866 int pixel = -1;
1867 if (m_pen.GetStyle () == wxTRANSPARENT)
1868 pixel = m_backgroundPixel;
1869 else
1870 {
1871 pixel = CalculatePixel(m_pen.GetColour(), m_currentColour, FALSE);
1872 }
1873
1874 // Finally, set the GC to the required colour
1875 if (pixel > -1)
1876 SetForegroundPixelWithLogicalFunction(pixel);
1877 }
1878 else
1879 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1880
1881 m_autoSetting = 0;
1882 }
1883
1884 void wxWindowDC::SetBrush( const wxBrush &brush )
1885 {
1886 wxCHECK_RET( Ok(), "invalid dc" );
1887
1888 m_brush = brush;
1889
1890 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1891 return;
1892
1893 int oldFill = m_currentFill;
1894 wxBitmap oldStipple = m_currentStipple;
1895
1896 m_autoSetting |= 0x1;
1897
1898 m_currentFill = m_brush.GetStyle ();
1899 if (m_currentFill == wxSTIPPLE)
1900 m_currentStipple = * m_brush.GetStipple ();
1901
1902 wxColour oldBrushColour(m_currentColour);
1903 m_currentColour = m_brush.GetColour ();
1904
1905 bool sameColour = (oldBrushColour.Ok () &&
1906 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1907 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1908 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1909 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1910
1911 int stippleDepth = -1;
1912
1913 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1914 {
1915 switch (brush.GetStyle ())
1916 {
1917 case wxTRANSPARENT:
1918 break;
1919 case wxSTIPPLE:
1920 stippleDepth = m_currentStipple.GetDepth();
1921 // fall through!
1922 case wxBDIAGONAL_HATCH:
1923 case wxCROSSDIAG_HATCH:
1924 case wxFDIAGONAL_HATCH:
1925 case wxCROSS_HATCH:
1926 case wxHORIZONTAL_HATCH:
1927 case wxVERTICAL_HATCH:
1928 {
1929 if (stippleDepth == -1) stippleDepth = 1;
1930
1931 // Chris Breeze 23/07/97: use background mode to
1932 // determine whether fill style should be solid or
1933 // transparent
1934 int style = stippleDepth == 1 ?
1935 (m_backgroundMode == wxSOLID ?
1936 FillOpaqueStippled : FillStippled) :
1937 FillTiled;
1938 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1939 if (m_window && m_window->GetBackingPixmap())
1940 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1941 }
1942 break;
1943 case wxSOLID:
1944 default:
1945 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1946 if (m_window && m_window->GetBackingPixmap())
1947 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking,
1948 FillSolid);
1949 }
1950 }
1951
1952 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1953 {
1954 Pixmap myStipple;
1955
1956 switch (m_currentFill)
1957 {
1958 case wxBDIAGONAL_HATCH:
1959 if (bdiag == (Pixmap) 0)
1960 bdiag = XCreateBitmapFromData ((Display*) m_display,
1961 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1962 bdiag_bits, bdiag_width, bdiag_height);
1963 myStipple = bdiag;
1964 break;
1965 case wxFDIAGONAL_HATCH:
1966 if (fdiag == (Pixmap) 0)
1967 fdiag = XCreateBitmapFromData ((Display*) m_display,
1968 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1969 fdiag_bits, fdiag_width, fdiag_height);
1970 myStipple = fdiag;
1971 break;
1972 case wxCROSS_HATCH:
1973 if (cross == (Pixmap) 0)
1974 cross = XCreateBitmapFromData ((Display*) m_display,
1975 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1976 cross_bits, cross_width, cross_height);
1977 myStipple = cross;
1978 break;
1979 case wxHORIZONTAL_HATCH:
1980 if (horiz == (Pixmap) 0)
1981 horiz = XCreateBitmapFromData ((Display*) m_display,
1982 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1983 horiz_bits, horiz_width, horiz_height);
1984 myStipple = horiz;
1985 break;
1986 case wxVERTICAL_HATCH:
1987 if (verti == (Pixmap) 0)
1988 verti = XCreateBitmapFromData ((Display*) m_display,
1989 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1990 verti_bits, verti_width, verti_height);
1991 myStipple = verti;
1992 break;
1993 case wxCROSSDIAG_HATCH:
1994 default:
1995 if (cdiag == (Pixmap) 0)
1996 cdiag = XCreateBitmapFromData ((Display*) m_display,
1997 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1998 cdiag_bits, cdiag_width, cdiag_height);
1999 myStipple = cdiag;
2000 break;
2001 }
2002 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
2003
2004 if (m_window && m_window->GetBackingPixmap())
2005 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
2006 }
2007 // X can forget the stipple value when resizing a window (apparently)
2008 // so always set the stipple.
2009 else if (m_currentFill != wxSOLID && m_currentFill != wxTRANSPARENT &&
2010 m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
2011 {
2012 if (m_currentStipple.GetDepth() == 1)
2013 {
2014 XSetStipple ((Display*) m_display, (GC) m_gc,
2015 (Pixmap) m_currentStipple.GetPixmap());
2016 if (m_window && m_window->GetBackingPixmap())
2017 XSetStipple ((Display*) m_display,(GC) m_gcBacking,
2018 (Pixmap) m_currentStipple.GetPixmap());
2019 }
2020 else
2021 {
2022 XSetTile ((Display*) m_display, (GC) m_gc,
2023 (Pixmap) m_currentStipple.GetPixmap());
2024 if (m_window && m_window->GetBackingPixmap())
2025 XSetTile ((Display*) m_display,(GC) m_gcBacking,
2026 (Pixmap) m_currentStipple.GetPixmap());
2027 }
2028 }
2029
2030 // must test m_logicalFunction, because it involves background!
2031 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
2032 {
2033 int pixel = CalculatePixel(m_brush.GetColour(), m_currentColour, TRUE);
2034
2035 if (pixel > -1)
2036 SetForegroundPixelWithLogicalFunction(pixel);
2037 }
2038 else
2039 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
2040 }
2041
2042 void wxWindowDC::SetBackground( const wxBrush &brush )
2043 {
2044 wxCHECK_RET( Ok(), "invalid dc" );
2045
2046 m_backgroundBrush = brush;
2047
2048 if (!m_backgroundBrush.Ok())
2049 return;
2050
2051 m_backgroundPixel = m_backgroundBrush.GetColour().AllocColour(m_display);
2052
2053 // New behaviour, 10/2/99: setting the background brush of a DC
2054 // doesn't affect the window background colour.
2055 /*
2056 // XSetWindowBackground doesn't work for non-Window pixmaps
2057 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2058 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2059 */
2060
2061 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2062 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2063 XSetBackground ((Display*) m_display, (GC) m_gc, m_backgroundPixel);
2064 if (m_window && m_window->GetBackingPixmap())
2065 XSetBackground ((Display*) m_display,(GC) m_gcBacking,
2066 m_backgroundPixel);
2067 }
2068
2069 void wxWindowDC::SetLogicalFunction( int function )
2070 {
2071 wxCHECK_RET( Ok(), "invalid dc" );
2072
2073 int x_function;
2074
2075 /* MATTHEW: [9] */
2076 if (m_logicalFunction == function)
2077 return;
2078
2079 switch (function)
2080 {
2081 case wxCLEAR:
2082 x_function = GXclear;
2083 break;
2084 case wxXOR:
2085 x_function = GXxor;
2086 break;
2087 case wxINVERT:
2088 x_function = GXinvert;
2089 break;
2090 case wxOR_REVERSE:
2091 x_function = GXorReverse;
2092 break;
2093 case wxAND_REVERSE:
2094 x_function = GXandReverse;
2095 break;
2096 case wxAND:
2097 x_function = GXand;
2098 break;
2099 case wxOR:
2100 x_function = GXor;
2101 break;
2102 case wxAND_INVERT:
2103 x_function = GXandInverted;
2104 break;
2105 case wxNO_OP:
2106 x_function = GXnoop;
2107 break;
2108 case wxNOR:
2109 x_function = GXnor;
2110 break;
2111 case wxEQUIV:
2112 x_function = GXequiv;
2113 break;
2114 case wxSRC_INVERT:
2115 x_function = GXcopyInverted;
2116 break;
2117 case wxOR_INVERT:
2118 x_function = GXorInverted;
2119 break;
2120 case wxNAND:
2121 x_function = GXnand;
2122 break;
2123 case wxSET:
2124 x_function = GXset;
2125 break;
2126 case wxCOPY:
2127 default:
2128 x_function = GXcopy;
2129 break;
2130 }
2131
2132 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
2133 if (m_window && m_window->GetBackingPixmap())
2134 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
2135
2136 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
2137 /* MATTHEW: [9] Need to redo pen simply */
2138 m_autoSetting |= 0x2;
2139
2140 m_logicalFunction = function;
2141
2142 }
2143
2144 void wxWindowDC::SetTextForeground( const wxColour &col )
2145 {
2146 wxCHECK_RET( Ok(), "invalid dc" );
2147
2148 if (m_textForegroundColour == col)
2149 return;
2150
2151 m_textForegroundColour = col;
2152
2153 }
2154
2155 void wxWindowDC::SetTextBackground( const wxColour &col )
2156 {
2157 wxCHECK_RET( Ok(), "invalid dc" );
2158
2159 if (m_textBackgroundColour == col)
2160 return;
2161
2162 m_textBackgroundColour = col;
2163 if (!m_textBackgroundColour.Ok())
2164 return;
2165 }
2166
2167 void wxWindowDC::SetBackgroundMode( int mode )
2168 {
2169 m_backgroundMode = mode;
2170 }
2171
2172 void wxWindowDC::SetPalette( const wxPalette& palette )
2173 {
2174 if (m_window)
2175 {
2176 if (palette.Ok())
2177 /* Use GetXColormap */
2178 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2179 (Colormap) palette.GetXColormap());
2180 else
2181 /* Use wxGetMainColormap */
2182 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2183 (Colormap) wxTheApp->GetMainColormap(m_display));
2184 }
2185 }
2186
2187 // Helper function
2188 void wxWindowDC::SetDCClipping()
2189 {
2190 // m_userRegion is the region set by calling SetClippingRegion
2191
2192 if (m_currentRegion)
2193 XDestroyRegion ((Region) m_currentRegion);
2194
2195 // We need to take into account
2196 // clipping imposed on a window by a repaint.
2197 // We'll combine it with the user region. But for now,
2198 // just use the currently-defined user clipping region.
2199 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
2200 m_currentRegion = (WXRegion) XCreateRegion ();
2201 else
2202 m_currentRegion = (WXRegion) NULL;
2203
2204 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2205 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
2206 else if (m_userRegion)
2207 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
2208 else if (m_window && m_window->GetUpdateRegion().Ok())
2209 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
2210 (Region) m_currentRegion);
2211
2212 if (m_currentRegion)
2213 {
2214 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
2215 }
2216 else
2217 {
2218 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2219 }
2220
2221 }
2222
2223 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
2224 {
2225 wxDC::DoSetClippingRegion( x, y, width, height );
2226
2227 if (m_userRegion)
2228 XDestroyRegion ((Region) m_userRegion);
2229 m_userRegion = (WXRegion) XCreateRegion ();
2230 XRectangle r;
2231 r.x = XLOG2DEV (x);
2232 r.y = YLOG2DEV (y);
2233 r.width = XLOG2DEVREL(width);
2234 r.height = YLOG2DEVREL(height);
2235 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
2236
2237 SetDCClipping ();
2238
2239 // Needs to work differently for Pixmap: without this,
2240 // there's a nasty (Display*) m_display bug. 8/12/94
2241 if (m_window && m_window->GetBackingPixmap())
2242 {
2243 XRectangle rects[1];
2244 rects[0].x = XLOG2DEV_2(x);
2245 rects[0].y = YLOG2DEV_2(y);
2246 rects[0].width = XLOG2DEVREL(width);
2247 rects[0].height = YLOG2DEVREL(height);
2248 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2249 }
2250 }
2251
2252 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2253 {
2254 wxRect box = region.GetBox();
2255
2256 wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height );
2257
2258 if (m_userRegion)
2259 XDestroyRegion ((Region) m_userRegion);
2260 m_userRegion = (WXRegion) XCreateRegion ();
2261
2262 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
2263
2264 SetDCClipping ();
2265
2266 // Needs to work differently for Pixmap: without this,
2267 // there's a nasty (Display*) m_display bug. 8/12/94
2268 if (m_window && m_window->GetBackingPixmap())
2269 {
2270 XRectangle rects[1];
2271 rects[0].x = XLOG2DEV_2(box.x);
2272 rects[0].y = YLOG2DEV_2(box.y);
2273 rects[0].width = XLOG2DEVREL(box.width);
2274 rects[0].height = YLOG2DEVREL(box.height);
2275 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2276 }
2277 }
2278
2279
2280 void wxWindowDC::DestroyClippingRegion()
2281 {
2282 wxDC::DestroyClippingRegion();
2283
2284 if (m_userRegion)
2285 XDestroyRegion ((Region) m_userRegion);
2286 m_userRegion = NULL;
2287
2288 SetDCClipping ();
2289
2290 XGCValues gc_val;
2291 gc_val.clip_mask = None;
2292 if (m_window && m_window->GetBackingPixmap())
2293 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
2294 }
2295
2296 // Resolution in pixels per logical inch
2297 wxSize wxWindowDC::GetPPI() const
2298 {
2299 return wxSize(100, 100);
2300 }
2301
2302 int wxWindowDC::GetDepth() const
2303 {
2304 // TODO
2305 return 24;
2306 }
2307
2308
2309
2310
2311 // ----------------------------------------------------------------------------
2312 // wxPaintDC
2313 // ----------------------------------------------------------------------------
2314
2315 wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win)
2316 {
2317 wxRegion* region = NULL;
2318
2319 // Combine all the update rects into a region
2320 const wxRectList& updateRects(win->GetUpdateRects());
2321 if ( updateRects.GetCount() != 0 )
2322 {
2323 for ( wxRectList::Node *node = updateRects.GetFirst();
2324 node;
2325 node = node->GetNext() )
2326 {
2327 wxRect* rect = node->GetData();
2328
2329 if (!region)
2330 region = new wxRegion(*rect);
2331 else
2332 // TODO: is this correct? In SetDCClipping above,
2333 // XIntersectRegion is used to combine paint and user
2334 // regions. XIntersectRegion appears to work in that case...
2335 region->Union(*rect);
2336 }
2337 }
2338 else
2339 {
2340 int cw, ch;
2341 win->GetClientSize(&cw, &ch);
2342 region = new wxRegion(wxRect(0, 0, cw, ch));
2343 }
2344
2345 win->SetUpdateRegion(*region);
2346
2347 wxRegion& theRegion(win->GetUpdateRegion());
2348 theRegion.SetRects(updateRects); // We also store in terms of rects, for iteration to work.
2349
2350 // Set the clipping region. Any user-defined region will be combined with this
2351 // one in SetDCClipping.
2352 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
2353
2354 delete region;
2355 }
2356
2357 wxPaintDC::~wxPaintDC()
2358 {
2359 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2360 if (m_window)
2361 m_window->ClearUpdateRegion();
2362 }
2363
2364 // ----------------------------------------------------------------------------
2365 // private functions
2366 // ----------------------------------------------------------------------------
2367
2368 /*
2369 Used when copying between drawables on different (Display*) m_displays. Not
2370 very fast, but better than giving up.
2371 */
2372
2373 static void XCopyRemote(Display *src_display, Display *dest_display,
2374 Drawable src, Drawable dest,
2375 GC destgc,
2376 int srcx, int srcy,
2377 unsigned int w, unsigned int h,
2378 int destx, int desty,
2379 bool more, XImage **cache)
2380 {
2381 XImage *image, *destimage;
2382 Colormap destcm, srccm;
2383 static const int CACHE_SIZE = 256;
2384
2385 unsigned int i, j;
2386 unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2387 int k, cache_pos, all_cache;
2388
2389 if (!cache || !*cache)
2390 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2391 else
2392 image = *cache;
2393
2394 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2395
2396 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2397 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2398
2399 cache_pos = 0;
2400 all_cache = FALSE;
2401
2402 for (i = 0; i < w; i++)
2403 for (j = 0; j < h; j++) {
2404 unsigned long pixel;
2405 XColor xcol;
2406
2407 pixel = XGetPixel(image, i, j);
2408 for (k = cache_pos; k--; )
2409 if (cachesrc[k] == pixel) {
2410 pixel = cachedest[k];
2411 goto install;
2412 }
2413 if (all_cache)
2414 for (k = CACHE_SIZE; k-- > cache_pos; )
2415 if (cachesrc[k] == pixel) {
2416 pixel = cachedest[k];
2417 goto install;
2418 }
2419
2420 cachesrc[cache_pos] = xcol.pixel = pixel;
2421 XQueryColor(src_display, srccm, &xcol);
2422 if (!XAllocColor(dest_display, destcm, &xcol))
2423 xcol.pixel = 0;
2424 cachedest[cache_pos] = pixel = xcol.pixel;
2425
2426 if (++cache_pos >= CACHE_SIZE) {
2427 cache_pos = 0;
2428 all_cache = TRUE;
2429 }
2430
2431 install:
2432 XPutPixel(destimage, i, j, pixel);
2433 }
2434
2435 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2436 XDestroyImage(destimage);
2437
2438 if (more)
2439 *cache = image;
2440 else
2441 XDestroyImage(image);
2442 }
2443
2444 #if 0
2445
2446 /* Helper function for 16-bit fonts */
2447 static int str16len(const char *s)
2448 {
2449 int count = 0;
2450
2451 while (s[0] && s[1]) {
2452 count++;
2453 s += 2;
2454 }
2455
2456 return count;
2457 }
2458
2459 #endif // 0