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