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