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