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