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