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