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