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