]> git.saurik.com Git - wxWidgets.git/blob - src/motif/dcclient.cpp
Rotated text patch from Hans-Joachim Baader (with some corrections)
[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 {
1272 DrawPoint(x1 + maxx - rx, cy + y1 - ry);
1273 }
1274 else
1275 {
1276 // Background
1277 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1278 }
1279 }
1280 }
1281 }
1282
1283 #if 0
1284 // First draw a rectangle representing the text background, if a text
1285 // background is specified
1286 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1287 {
1288 wxColour oldPenColour = m_currentColour;
1289 m_currentColour = m_textBackgroundColour;
1290 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1291 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1292 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1293 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1294
1295 // This separation of the big && test required for gcc2.7/HP UX 9.02
1296 // or pixel value can be corrupted!
1297 sameColour = (sameColour &&
1298 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1299
1300 if (!sameColour || !GetOptimization())
1301 {
1302 int pixel = m_textBackgroundColour.AllocColour(m_display);
1303 m_currentColour = m_textBackgroundColour;
1304
1305 // Set the GC to the required colour
1306 if (pixel > -1)
1307 {
1308 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1309 if (m_window && m_window->GetBackingPixmap())
1310 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1311 }
1312 }
1313 else
1314 m_textBackgroundColour = oldPenColour ;
1315
1316 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1317 if (m_window && m_window->GetBackingPixmap())
1318 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1319 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1320 }
1321 #endif
1322
1323 long w, h;
1324 // XXX use pixmap size
1325 GetTextExtent (text, &w, &h);
1326 CalcBoundingBox (x + w, y + h);
1327 CalcBoundingBox (x, y);
1328 }
1329
1330 bool wxWindowDC::CanGetTextExtent() const
1331 {
1332 return TRUE;
1333 }
1334
1335 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1336 wxCoord *descent, wxCoord *externalLeading,
1337 wxFont *font ) const
1338 {
1339 wxCHECK_RET( Ok(), "invalid dc" );
1340
1341 wxFont* theFont = font;
1342 if (!theFont)
1343 theFont = (wxFont *)&m_font; // const_cast
1344
1345 if (!theFont->Ok())
1346 {
1347 // TODO: this should be an error log function
1348 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1349
1350 if (width) *width = -1;
1351 if (height) *height = -1;
1352 return;
1353 }
1354
1355 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1356
1357 int direction, ascent, descent2;
1358 XCharStruct overall;
1359 int slen;
1360
1361 #if 0
1362 if (use16)
1363 slen = str16len(string);
1364 else
1365 #endif // 0
1366 slen = strlen(string);
1367
1368 #if 0
1369 if (use16)
1370 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1371 &ascent, &descent2, &overall);
1372 else
1373 #endif // 0
1374 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1375 &ascent, &descent2, &overall);
1376
1377 if (width) *width = XDEV2LOGREL (overall.width);
1378 if (height) *height = YDEV2LOGREL (ascent + descent2);
1379 if (descent)
1380 *descent = descent2;
1381 if (externalLeading)
1382 *externalLeading = 0;
1383 }
1384
1385 wxCoord wxWindowDC::GetCharWidth() const
1386 {
1387 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1388 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1389
1390 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
1391
1392 int direction, ascent, descent;
1393 XCharStruct overall;
1394 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1395 &descent, &overall);
1396 return XDEV2LOGREL(overall.width);
1397 }
1398
1399 wxCoord wxWindowDC::GetCharHeight() const
1400 {
1401 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1402 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1403
1404 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1405
1406 int direction, ascent, descent;
1407 XCharStruct overall;
1408 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1409 &descent, &overall);
1410 // return XDEV2LOGREL(overall.ascent + overall.descent);
1411 return XDEV2LOGREL(ascent + descent);
1412 }
1413
1414 void wxWindowDC::Clear()
1415 {
1416 wxCHECK_RET( Ok(), "invalid dc" );
1417
1418 int w, h;
1419 if (m_window)
1420 {
1421 m_window->GetSize(&w, &h);
1422
1423 if (m_window && m_window->GetBackingPixmap())
1424 {
1425 w = m_window->GetPixmapWidth();
1426 h = m_window->GetPixmapHeight();
1427 }
1428 }
1429 else
1430 {
1431 if (this->IsKindOf(CLASSINFO(wxMemoryDC)))
1432 {
1433 wxMemoryDC* memDC = (wxMemoryDC*) this;
1434 w = memDC->GetBitmap().GetWidth();
1435 h = memDC->GetBitmap().GetHeight();
1436 }
1437 else
1438 return;
1439 }
1440
1441 wxBrush saveBrush = m_brush;
1442 SetBrush (m_backgroundBrush);
1443
1444 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, 0, w, h);
1445
1446 if (m_window && m_window->GetBackingPixmap())
1447 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 0, 0, w, h);
1448
1449 m_brush = saveBrush;
1450 }
1451
1452 void wxWindowDC::Clear(const wxRect& rect)
1453 {
1454 wxCHECK_RET( Ok(), "invalid dc" );
1455
1456 int x = rect.x; int y = rect.y;
1457 int w = rect.width; int h = rect.height;
1458
1459 wxBrush saveBrush = m_brush;
1460 SetBrush (m_backgroundBrush);
1461
1462 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
1463
1464 if (m_window && m_window->GetBackingPixmap())
1465 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
1466
1467 m_brush = saveBrush;
1468 }
1469
1470 void wxWindowDC::SetFont( const wxFont &font )
1471 {
1472 wxCHECK_RET( Ok(), "invalid dc" );
1473
1474 m_font = font;
1475
1476 if (!m_font.Ok())
1477 {
1478 if ((m_oldFont != (WXFont) 0) && ((wxCoord) m_oldFont != -1))
1479 {
1480 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
1481
1482 if (m_window && m_window->GetBackingPixmap())
1483 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1484 }
1485 return;
1486 }
1487
1488 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1489
1490 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1491 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1492
1493 if (m_window && m_window->GetBackingPixmap())
1494 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
1495 }
1496
1497 void wxWindowDC::SetPen( const wxPen &pen )
1498 {
1499 wxCHECK_RET( Ok(), "invalid dc" );
1500
1501 m_pen = pen;
1502 if (!m_pen.Ok())
1503 return;
1504
1505 wxBitmap oldStipple = m_currentStipple;
1506 int oldStyle = m_currentStyle;
1507 int oldFill = m_currentFill;
1508 int old_pen_width = m_currentPenWidth;
1509 int old_pen_join = m_currentPenJoin;
1510 int old_pen_cap = m_currentPenCap;
1511 int old_pen_nb_dash = m_currentPenDashCount;
1512 char *old_pen_dash = m_currentPenDash;
1513
1514 wxColour oldPenColour = m_currentColour;
1515 m_currentColour = m_pen.GetColour ();
1516 m_currentStyle = m_pen.GetStyle ();
1517 m_currentFill = m_pen.GetStyle (); // TODO?
1518 m_currentPenWidth = m_pen.GetWidth ();
1519 m_currentPenJoin = m_pen.GetJoin ();
1520 m_currentPenCap = m_pen.GetCap ();
1521 m_currentPenDashCount = m_pen.GetDashCount();
1522 m_currentPenDash = m_pen.GetDash();
1523
1524 if (m_currentStyle == wxSTIPPLE)
1525 m_currentStipple = * m_pen.GetStipple ();
1526
1527 bool sameStyle = (oldStyle == m_currentStyle &&
1528 oldFill == m_currentFill &&
1529 old_pen_join == m_currentPenJoin &&
1530 old_pen_cap == m_currentPenCap &&
1531 old_pen_nb_dash == m_currentPenDashCount &&
1532 old_pen_dash == m_currentPenDash &&
1533 old_pen_width == m_currentPenWidth);
1534
1535 bool sameColour = (oldPenColour.Ok () &&
1536 (oldPenColour.Red () == m_currentColour.Red ()) &&
1537 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1538 (oldPenColour.Green () == m_currentColour.Green ()) &&
1539 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1540
1541 if (!sameStyle || !GetOptimization())
1542 {
1543 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1544 if (scaled_width < 0)
1545 scaled_width = 0;
1546
1547 int style;
1548 int join;
1549 int cap;
1550 static const char dotted[] = {2, 5};
1551 static const char short_dashed[] = {4, 4};
1552 static const char long_dashed[] = {4, 8};
1553 static const char dotted_dashed[] = {6, 6, 2, 6};
1554
1555 // We express dash pattern in pen width unit, so we are
1556 // independent of zoom factor and so on...
1557 int req_nb_dash;
1558 const char *req_dash;
1559
1560 switch (m_pen.GetStyle ())
1561 {
1562 case wxUSER_DASH:
1563 req_nb_dash = m_currentPenDashCount;
1564 req_dash = m_currentPenDash;
1565 style = LineOnOffDash;
1566 break;
1567 case wxDOT:
1568 req_nb_dash = 2;
1569 req_dash = dotted;
1570 style = LineOnOffDash;
1571 break;
1572 case wxSHORT_DASH:
1573 req_nb_dash = 2;
1574 req_dash = short_dashed;
1575 style = LineOnOffDash;
1576 break;
1577 case wxLONG_DASH:
1578 req_nb_dash = 2;
1579 req_dash = long_dashed;
1580 style = LineOnOffDash;
1581 break;
1582 case wxDOT_DASH:
1583 req_nb_dash = 4;
1584 req_dash = dotted_dashed;
1585 style = LineOnOffDash;
1586 break;
1587 case wxSTIPPLE:
1588 case wxSOLID:
1589 case wxTRANSPARENT:
1590 default:
1591 style = LineSolid;
1592 req_dash = NULL;
1593 req_nb_dash = 0;
1594 }
1595
1596 if (req_dash && req_nb_dash)
1597 {
1598 char *real_req_dash = new char[req_nb_dash];
1599 if (real_req_dash)
1600 {
1601 int factor = scaled_width == 0 ? 1 : scaled_width;
1602 for (int i = 0; i < req_nb_dash; i++)
1603 real_req_dash[i] = req_dash[i] * factor;
1604 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1605
1606 if (m_window && m_window->GetBackingPixmap())
1607 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1608 delete[]real_req_dash;
1609 }
1610 else
1611 {
1612 // No Memory. We use non-scaled dash pattern...
1613 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1614
1615 if (m_window && m_window->GetBackingPixmap())
1616 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1617 }
1618 }
1619
1620 switch (m_pen.GetCap ())
1621 {
1622 case wxCAP_PROJECTING:
1623 cap = CapProjecting;
1624 break;
1625 case wxCAP_BUTT:
1626 cap = CapButt;
1627 break;
1628 case wxCAP_ROUND:
1629 default:
1630 cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1631 break;
1632 }
1633
1634 switch (m_pen.GetJoin ())
1635 {
1636 case wxJOIN_BEVEL:
1637 join = JoinBevel;
1638 break;
1639 case wxJOIN_MITER:
1640 join = JoinMiter;
1641 break;
1642 case wxJOIN_ROUND:
1643 default:
1644 join = JoinRound;
1645 break;
1646 }
1647
1648 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1649
1650 if (m_window && m_window->GetBackingPixmap())
1651 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1652 }
1653
1654 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1655 {
1656 Pixmap myStipple;
1657
1658 oldStipple = wxNullBitmap; // For later reset!!
1659
1660 switch (m_currentFill)
1661 {
1662 case wxBDIAGONAL_HATCH:
1663 if (bdiag == (Pixmap) 0)
1664 bdiag = XCreateBitmapFromData ((Display*) m_display,
1665 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1666 bdiag_bits, bdiag_width, bdiag_height);
1667 myStipple = bdiag;
1668 break;
1669 case wxFDIAGONAL_HATCH:
1670 if (fdiag == (Pixmap) 0)
1671 fdiag = XCreateBitmapFromData ((Display*) m_display,
1672 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1673 fdiag_bits, fdiag_width, fdiag_height);
1674 myStipple = fdiag;
1675 break;
1676 case wxCROSS_HATCH:
1677 if (cross == (Pixmap) 0)
1678 cross = XCreateBitmapFromData ((Display*) m_display,
1679 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1680 cross_bits, cross_width, cross_height);
1681 myStipple = cross;
1682 break;
1683 case wxHORIZONTAL_HATCH:
1684 if (horiz == (Pixmap) 0)
1685 horiz = XCreateBitmapFromData ((Display*) m_display,
1686 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1687 horiz_bits, horiz_width, horiz_height);
1688 myStipple = horiz;
1689 break;
1690 case wxVERTICAL_HATCH:
1691 if (verti == (Pixmap) 0)
1692 verti = XCreateBitmapFromData ((Display*) m_display,
1693 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1694 verti_bits, verti_width, verti_height);
1695 myStipple = verti;
1696 break;
1697 case wxCROSSDIAG_HATCH:
1698 default:
1699 if (cdiag == (Pixmap) 0)
1700 cdiag = XCreateBitmapFromData ((Display*) m_display,
1701 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1702 cdiag_bits, cdiag_width, cdiag_height);
1703 myStipple = cdiag;
1704 break;
1705 }
1706 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1707
1708 if (m_window && m_window->GetBackingPixmap())
1709 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1710 }
1711 else if (m_currentStipple.Ok()
1712 && ((m_currentStipple != oldStipple) || !GetOptimization()))
1713 {
1714 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1715
1716 if (m_window && m_window->GetBackingPixmap())
1717 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1718 }
1719
1720 if ((m_currentFill != oldFill) || !GetOptimization())
1721 {
1722 int fill_style;
1723
1724 if (m_currentFill == wxSTIPPLE)
1725 fill_style = FillStippled;
1726 else if (IS_HATCH (m_currentFill))
1727 fill_style = FillStippled;
1728 else
1729 fill_style = FillSolid;
1730 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1731 if (m_window && m_window->GetBackingPixmap())
1732 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1733 }
1734
1735 // must test m_logicalFunction, because it involves background!
1736 if (!sameColour || !GetOptimization()
1737 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1738 {
1739 int pixel = -1;
1740 if (m_pen.GetStyle () == wxTRANSPARENT)
1741 pixel = m_backgroundPixel;
1742 else if (!m_colour)
1743 {
1744 unsigned char red = m_pen.GetColour ().Red ();
1745 unsigned char blue = m_pen.GetColour ().Blue ();
1746 unsigned char green = m_pen.GetColour ().Green ();
1747 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1748 && green == (unsigned char) 255)
1749 {
1750 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1751 m_currentColour = *wxWHITE;
1752 m_pen.GetColour().SetPixel(pixel);
1753 m_currentColour.SetPixel(pixel);
1754 }
1755 else
1756 {
1757 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1758 m_currentColour = *wxBLACK;
1759 m_pen.GetColour().SetPixel(pixel);
1760 }
1761 }
1762 else
1763 {
1764 pixel = m_pen.GetColour ().AllocColour(m_display);
1765 m_currentColour.SetPixel(pixel);
1766 }
1767
1768 // Finally, set the GC to the required colour
1769 if (pixel > -1)
1770 {
1771 if (m_logicalFunction == wxXOR)
1772 {
1773 XGCValues values;
1774 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1775 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1776 if (m_window && m_window->GetBackingPixmap())
1777 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1778 }
1779 else
1780 {
1781 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1782 if (m_window && m_window->GetBackingPixmap())
1783 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1784 }
1785 }
1786 }
1787 else
1788 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1789
1790 m_autoSetting = 0;
1791 }
1792
1793 void wxWindowDC::SetBrush( const wxBrush &brush )
1794 {
1795 wxCHECK_RET( Ok(), "invalid dc" );
1796
1797 m_brush = brush;
1798
1799 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1800 return;
1801
1802 int oldFill = m_currentFill;
1803 wxBitmap oldStipple = m_currentStipple;
1804
1805 m_autoSetting |= 0x1;
1806
1807 m_currentFill = m_brush.GetStyle ();
1808 if (m_currentFill == wxSTIPPLE)
1809 m_currentStipple = * m_brush.GetStipple ();
1810
1811 wxColour oldBrushColour(m_currentColour);
1812 m_currentColour = m_brush.GetColour ();
1813
1814 bool sameColour = (oldBrushColour.Ok () &&
1815 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1816 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1817 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1818 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1819
1820 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1821 {
1822 switch (brush.GetStyle ())
1823 {
1824 case wxTRANSPARENT:
1825 break;
1826 case wxBDIAGONAL_HATCH:
1827 case wxCROSSDIAG_HATCH:
1828 case wxFDIAGONAL_HATCH:
1829 case wxCROSS_HATCH:
1830 case wxHORIZONTAL_HATCH:
1831 case wxVERTICAL_HATCH:
1832 case wxSTIPPLE:
1833 {
1834 // Chris Breeze 23/07/97: use background mode to determine whether
1835 // fill style should be solid or transparent
1836 int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled);
1837 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1838 if (m_window && m_window->GetBackingPixmap())
1839 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1840 }
1841 break;
1842 case wxSOLID:
1843 default:
1844 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1845 if (m_window && m_window->GetBackingPixmap())
1846 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, FillSolid);
1847 }
1848 }
1849
1850 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1851 {
1852 Pixmap myStipple;
1853
1854 switch (m_currentFill)
1855 {
1856 case wxBDIAGONAL_HATCH:
1857 if (bdiag == (Pixmap) 0)
1858 bdiag = XCreateBitmapFromData ((Display*) m_display,
1859 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1860 bdiag_bits, bdiag_width, bdiag_height);
1861 myStipple = bdiag;
1862 break;
1863 case wxFDIAGONAL_HATCH:
1864 if (fdiag == (Pixmap) 0)
1865 fdiag = XCreateBitmapFromData ((Display*) m_display,
1866 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1867 fdiag_bits, fdiag_width, fdiag_height);
1868 myStipple = fdiag;
1869 break;
1870 case wxCROSS_HATCH:
1871 if (cross == (Pixmap) 0)
1872 cross = XCreateBitmapFromData ((Display*) m_display,
1873 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1874 cross_bits, cross_width, cross_height);
1875 myStipple = cross;
1876 break;
1877 case wxHORIZONTAL_HATCH:
1878 if (horiz == (Pixmap) 0)
1879 horiz = XCreateBitmapFromData ((Display*) m_display,
1880 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1881 horiz_bits, horiz_width, horiz_height);
1882 myStipple = horiz;
1883 break;
1884 case wxVERTICAL_HATCH:
1885 if (verti == (Pixmap) 0)
1886 verti = XCreateBitmapFromData ((Display*) m_display,
1887 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1888 verti_bits, verti_width, verti_height);
1889 myStipple = verti;
1890 break;
1891 case wxCROSSDIAG_HATCH:
1892 default:
1893 if (cdiag == (Pixmap) 0)
1894 cdiag = XCreateBitmapFromData ((Display*) m_display,
1895 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1896 cdiag_bits, cdiag_width, cdiag_height);
1897 myStipple = cdiag;
1898 break;
1899 }
1900 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1901
1902 if (m_window && m_window->GetBackingPixmap())
1903 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1904 }
1905 // X can forget the stipple value when resizing a window (apparently)
1906 // so always set the stipple.
1907 else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1908 {
1909 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1910 if (m_window && m_window->GetBackingPixmap())
1911 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1912 }
1913
1914 // must test m_logicalFunction, because it involves background!
1915 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
1916 {
1917 int pixel = -1;
1918 if (!m_colour)
1919 {
1920 // Policy - on a monochrome screen, all brushes are white,
1921 // except when they're REALLY black!!!
1922 unsigned char red = m_brush.GetColour ().Red ();
1923 unsigned char blue = m_brush.GetColour ().Blue ();
1924 unsigned char green = m_brush.GetColour ().Green ();
1925
1926 if (red == (unsigned char) 0 && blue == (unsigned char) 0
1927 && green == (unsigned char) 0)
1928 {
1929 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1930 m_currentColour = *wxBLACK;
1931 m_brush.GetColour().SetPixel(pixel);
1932 m_currentColour.SetPixel(pixel);
1933 }
1934 else
1935 {
1936 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1937 m_currentColour = *wxWHITE;
1938 m_brush.GetColour().SetPixel(pixel);
1939 m_currentColour.SetPixel(pixel);
1940 }
1941
1942 // N.B. comment out the above line and uncomment the following lines
1943 // if you want non-white colours to be black on a monochrome display.
1944 /*
1945 if (red == (unsigned char )255 && blue == (unsigned char)255
1946 && green == (unsigned char)255)
1947 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1948 else
1949 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1950 */
1951 }
1952 else if (m_brush.GetStyle () != wxTRANSPARENT)
1953 {
1954 pixel = m_brush.GetColour().AllocColour(m_display);
1955 m_currentColour.SetPixel(pixel);
1956 }
1957 if (pixel > -1)
1958 {
1959 // Finally, set the GC to the required colour
1960 if (m_logicalFunction == wxXOR)
1961 {
1962 XGCValues values;
1963 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1964 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1965 if (m_window && m_window->GetBackingPixmap())
1966 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1967 }
1968 else
1969 {
1970 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1971 if (m_window && m_window->GetBackingPixmap())
1972 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1973 }
1974 }
1975 }
1976 else
1977 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
1978 }
1979
1980 void wxWindowDC::SetBackground( const wxBrush &brush )
1981 {
1982 wxCHECK_RET( Ok(), "invalid dc" );
1983
1984 m_backgroundBrush = brush;
1985
1986 if (!m_backgroundBrush.Ok())
1987 return;
1988
1989 int pixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1990
1991 // New behaviour, 10/2/99: setting the background brush of a DC
1992 // doesn't affect the window background colour.
1993 /*
1994 // XSetWindowBackground doesn't work for non-Window pixmaps
1995 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1996 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1997 */
1998
1999 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2000 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2001 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
2002 if (m_window && m_window->GetBackingPixmap())
2003 XSetBackground ((Display*) m_display,(GC) m_gcBacking, pixel);
2004 }
2005
2006 void wxWindowDC::SetLogicalFunction( int function )
2007 {
2008 wxCHECK_RET( Ok(), "invalid dc" );
2009
2010 int x_function;
2011
2012 /* MATTHEW: [9] */
2013 if (m_logicalFunction == function)
2014 return;
2015
2016 switch (function)
2017 {
2018 case wxCLEAR:
2019 x_function = GXclear;
2020 break;
2021 case wxXOR:
2022 x_function = GXxor;
2023 break;
2024 case wxINVERT:
2025 x_function = GXinvert;
2026 break;
2027 case wxOR_REVERSE:
2028 x_function = GXorReverse;
2029 break;
2030 case wxAND_REVERSE:
2031 x_function = GXandReverse;
2032 break;
2033 case wxAND:
2034 x_function = GXand;
2035 break;
2036 case wxOR:
2037 x_function = GXor;
2038 break;
2039 case wxAND_INVERT:
2040 x_function = GXandInverted;
2041 break;
2042 case wxNO_OP:
2043 x_function = GXnoop;
2044 break;
2045 case wxNOR:
2046 x_function = GXnor;
2047 break;
2048 case wxEQUIV:
2049 x_function = GXequiv;
2050 break;
2051 case wxSRC_INVERT:
2052 x_function = GXcopyInverted;
2053 break;
2054 case wxOR_INVERT:
2055 x_function = GXorInverted;
2056 break;
2057 case wxNAND:
2058 x_function = GXnand;
2059 break;
2060 case wxSET:
2061 x_function = GXset;
2062 break;
2063 case wxCOPY:
2064 default:
2065 x_function = GXcopy;
2066 break;
2067 }
2068
2069 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
2070 if (m_window && m_window->GetBackingPixmap())
2071 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
2072
2073 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
2074 /* MATTHEW: [9] Need to redo pen simply */
2075 m_autoSetting |= 0x2;
2076
2077 m_logicalFunction = function;
2078
2079 }
2080
2081 void wxWindowDC::SetTextForeground( const wxColour &col )
2082 {
2083 wxCHECK_RET( Ok(), "invalid dc" );
2084
2085 if (m_textForegroundColour == col)
2086 return;
2087
2088 m_textForegroundColour = col;
2089
2090 }
2091
2092 void wxWindowDC::SetTextBackground( const wxColour &col )
2093 {
2094 wxCHECK_RET( Ok(), "invalid dc" );
2095
2096 if (m_textBackgroundColour == col)
2097 return;
2098
2099 m_textBackgroundColour = col;
2100 if (!m_textBackgroundColour.Ok())
2101 return;
2102 }
2103
2104 void wxWindowDC::SetBackgroundMode( int mode )
2105 {
2106 m_backgroundMode = mode;
2107 }
2108
2109 void wxWindowDC::SetPalette( const wxPalette& palette )
2110 {
2111 if (m_window)
2112 {
2113 if (palette.Ok())
2114 /* Use GetXColormap */
2115 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2116 (Colormap) palette.GetXColormap());
2117 else
2118 /* Use wxGetMainColormap */
2119 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2120 (Colormap) wxTheApp->GetMainColormap(m_display));
2121 }
2122 }
2123
2124 // Helper function
2125 void wxWindowDC::SetDCClipping()
2126 {
2127 // m_userRegion is the region set by calling SetClippingRegion
2128
2129 if (m_currentRegion)
2130 XDestroyRegion ((Region) m_currentRegion);
2131
2132 // We need to take into account
2133 // clipping imposed on a window by a repaint.
2134 // We'll combine it with the user region. But for now,
2135 // just use the currently-defined user clipping region.
2136 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
2137 m_currentRegion = (WXRegion) XCreateRegion ();
2138 else
2139 m_currentRegion = (WXRegion) NULL;
2140
2141 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2142 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
2143 else if (m_userRegion)
2144 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
2145 else if (m_window && m_window->GetUpdateRegion().Ok())
2146 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
2147 (Region) m_currentRegion);
2148
2149 if (m_currentRegion)
2150 {
2151 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
2152 }
2153 else
2154 {
2155 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2156 }
2157
2158 }
2159
2160 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
2161 {
2162 wxDC::DoSetClippingRegion( x, y, width, height );
2163
2164 if (m_userRegion)
2165 XDestroyRegion ((Region) m_userRegion);
2166 m_userRegion = (WXRegion) XCreateRegion ();
2167 XRectangle r;
2168 r.x = XLOG2DEV (x);
2169 r.y = YLOG2DEV (y);
2170 r.width = XLOG2DEVREL(width);
2171 r.height = YLOG2DEVREL(height);
2172 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
2173
2174 SetDCClipping ();
2175
2176 // Needs to work differently for Pixmap: without this,
2177 // there's a nasty (Display*) m_display bug. 8/12/94
2178 if (m_window && m_window->GetBackingPixmap())
2179 {
2180 XRectangle rects[1];
2181 rects[0].x = XLOG2DEV_2(x);
2182 rects[0].y = YLOG2DEV_2(y);
2183 rects[0].width = XLOG2DEVREL(width);
2184 rects[0].height = YLOG2DEVREL(height);
2185 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2186 }
2187 }
2188
2189 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2190 {
2191 wxRect box = region.GetBox();
2192
2193 wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height );
2194
2195 if (m_userRegion)
2196 XDestroyRegion ((Region) m_userRegion);
2197 m_userRegion = (WXRegion) XCreateRegion ();
2198
2199 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
2200
2201 SetDCClipping ();
2202
2203 // Needs to work differently for Pixmap: without this,
2204 // there's a nasty (Display*) m_display bug. 8/12/94
2205 if (m_window && m_window->GetBackingPixmap())
2206 {
2207 XRectangle rects[1];
2208 rects[0].x = XLOG2DEV_2(box.x);
2209 rects[0].y = YLOG2DEV_2(box.y);
2210 rects[0].width = XLOG2DEVREL(box.width);
2211 rects[0].height = YLOG2DEVREL(box.height);
2212 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2213 }
2214 }
2215
2216
2217 void wxWindowDC::DestroyClippingRegion()
2218 {
2219 wxDC::DestroyClippingRegion();
2220
2221 if (m_userRegion)
2222 XDestroyRegion ((Region) m_userRegion);
2223 m_userRegion = NULL;
2224
2225 SetDCClipping ();
2226
2227 XGCValues gc_val;
2228 gc_val.clip_mask = None;
2229 if (m_window && m_window->GetBackingPixmap())
2230 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
2231 }
2232
2233 // Resolution in pixels per logical inch
2234 wxSize wxWindowDC::GetPPI() const
2235 {
2236 return wxSize(100, 100);
2237 }
2238
2239 int wxWindowDC::GetDepth() const
2240 {
2241 // TODO
2242 return 24;
2243 }
2244
2245 #if wxUSE_SPLINES
2246 // ----------------------------------- spline code ----------------------------------------
2247
2248 void wx_quadratic_spline(double a1, double b1, double a2, double b2,
2249 double a3, double b3, double a4, double b4);
2250 void wx_clear_stack();
2251 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
2252 double *y3, double *x4, double *y4);
2253 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
2254 double x4, double y4);
2255 static bool wx_spline_add_point(double x, double y);
2256 static void wx_spline_draw_point_array(wxDC *dc);
2257
2258 wxList wx_spline_point_list;
2259
2260 #define half(z1, z2) ((z1+z2)/2.0)
2261 #define THRESHOLD 5
2262
2263 /* iterative version */
2264
2265 void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
2266 double b4)
2267 {
2268 register double xmid, ymid;
2269 double x1, y1, x2, y2, x3, y3, x4, y4;
2270
2271 wx_clear_stack();
2272 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
2273
2274 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
2275 xmid = (double)half(x2, x3);
2276 ymid = (double)half(y2, y3);
2277 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
2278 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
2279 wx_spline_add_point( x1, y1 );
2280 wx_spline_add_point( xmid, ymid );
2281 } else {
2282 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
2283 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
2284 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
2285 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
2286 }
2287 }
2288 }
2289
2290 /* utilities used by spline drawing routines */
2291
2292 typedef struct wx_spline_stack_struct {
2293 double x1, y1, x2, y2, x3, y3, x4, y4;
2294 } Stack;
2295
2296 #define SPLINE_STACK_DEPTH 20
2297 static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
2298 static Stack *wx_stack_top;
2299 static int wx_stack_count;
2300
2301 void wx_clear_stack()
2302 {
2303 wx_stack_top = wx_spline_stack;
2304 wx_stack_count = 0;
2305 }
2306
2307 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
2308 {
2309 wx_stack_top->x1 = x1;
2310 wx_stack_top->y1 = y1;
2311 wx_stack_top->x2 = x2;
2312 wx_stack_top->y2 = y2;
2313 wx_stack_top->x3 = x3;
2314 wx_stack_top->y3 = y3;
2315 wx_stack_top->x4 = x4;
2316 wx_stack_top->y4 = y4;
2317 wx_stack_top++;
2318 wx_stack_count++;
2319 }
2320
2321 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
2322 double *x3, double *y3, double *x4, double *y4)
2323 {
2324 if (wx_stack_count == 0)
2325 return (0);
2326 wx_stack_top--;
2327 wx_stack_count--;
2328 *x1 = wx_stack_top->x1;
2329 *y1 = wx_stack_top->y1;
2330 *x2 = wx_stack_top->x2;
2331 *y2 = wx_stack_top->y2;
2332 *x3 = wx_stack_top->x3;
2333 *y3 = wx_stack_top->y3;
2334 *x4 = wx_stack_top->x4;
2335 *y4 = wx_stack_top->y4;
2336 return (1);
2337 }
2338
2339 static bool wx_spline_add_point(double x, double y)
2340 {
2341 wxPoint *point = new wxPoint ;
2342 point->x = (int) x;
2343 point->y = (int) y;
2344 wx_spline_point_list.Append((wxObject*)point);
2345 return TRUE;
2346 }
2347
2348 static void wx_spline_draw_point_array(wxDC *dc)
2349 {
2350 dc->DrawLines(&wx_spline_point_list, 0, 0 );
2351 wxNode *node = wx_spline_point_list.First();
2352 while (node)
2353 {
2354 wxPoint *point = (wxPoint *)node->Data();
2355 delete point;
2356 delete node;
2357 node = wx_spline_point_list.First();
2358 }
2359 }
2360
2361 void wxWindowDC::DoDrawSpline( wxList *points )
2362 {
2363 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2364
2365 wxPoint *p;
2366 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
2367 double x1, y1, x2, y2;
2368
2369 wxNode *node = points->First();
2370 p = (wxPoint *)node->Data();
2371
2372 x1 = p->x;
2373 y1 = p->y;
2374
2375 node = node->Next();
2376 p = (wxPoint *)node->Data();
2377
2378 x2 = p->x;
2379 y2 = p->y;
2380 cx1 = (double)((x1 + x2) / 2);
2381 cy1 = (double)((y1 + y2) / 2);
2382 cx2 = (double)((cx1 + x2) / 2);
2383 cy2 = (double)((cy1 + y2) / 2);
2384
2385 wx_spline_add_point(x1, y1);
2386
2387 while ((node = node->Next()) != NULL)
2388 {
2389 p = (wxPoint *)node->Data();
2390 x1 = x2;
2391 y1 = y2;
2392 x2 = p->x;
2393 y2 = p->y;
2394 cx4 = (double)(x1 + x2) / 2;
2395 cy4 = (double)(y1 + y2) / 2;
2396 cx3 = (double)(x1 + cx4) / 2;
2397 cy3 = (double)(y1 + cy4) / 2;
2398
2399 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
2400
2401 cx1 = cx4;
2402 cy1 = cy4;
2403 cx2 = (double)(cx1 + x2) / 2;
2404 cy2 = (double)(cy1 + y2) / 2;
2405 }
2406
2407 wx_spline_add_point( cx1, cy1 );
2408 wx_spline_add_point( x2, y2 );
2409
2410 wx_spline_draw_point_array( this );
2411 }
2412
2413 #endif // wxUSE_SPLINE
2414
2415
2416
2417 // ----------------------------------------------------------------------------
2418 // wxPaintDC
2419 // ----------------------------------------------------------------------------
2420
2421 wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win)
2422 {
2423 wxRegion* region = NULL;
2424
2425 // Combine all the update rects into a region
2426 const wxRectList& updateRects(win->GetUpdateRects());
2427 if ( updateRects.GetCount() != 0 )
2428 {
2429 for ( wxRectList::Node *node = updateRects.GetFirst();
2430 node;
2431 node = node->GetNext() )
2432 {
2433 wxRect* rect = node->GetData();
2434
2435 if (!region)
2436 region = new wxRegion(*rect);
2437 else
2438 // TODO: is this correct? In SetDCClipping above,
2439 // XIntersectRegion is used to combine paint and user
2440 // regions. XIntersectRegion appears to work in that case...
2441 region->Union(*rect);
2442 }
2443 }
2444 else
2445 {
2446 int cw, ch;
2447 win->GetClientSize(&cw, &ch);
2448 region = new wxRegion(wxRect(0, 0, cw, ch));
2449 }
2450
2451 win->SetUpdateRegion(*region);
2452
2453 wxRegion& theRegion(win->GetUpdateRegion());
2454 theRegion.SetRects(updateRects); // We also store in terms of rects, for iteration to work.
2455
2456 // Set the clipping region. Any user-defined region will be combined with this
2457 // one in SetDCClipping.
2458 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
2459
2460 delete region;
2461 }
2462
2463 wxPaintDC::~wxPaintDC()
2464 {
2465 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2466 if (m_window)
2467 m_window->ClearUpdateRegion();
2468 }
2469
2470 // ----------------------------------------------------------------------------
2471 // private functions
2472 // ----------------------------------------------------------------------------
2473
2474 /*
2475 Used when copying between drawables on different (Display*) m_displays. Not
2476 very fast, but better than giving up.
2477 */
2478
2479 static void XCopyRemote(Display *src_display, Display *dest_display,
2480 Drawable src, Drawable dest,
2481 GC destgc,
2482 int srcx, int srcy,
2483 unsigned int w, unsigned int h,
2484 int destx, int desty,
2485 bool more, XImage **cache)
2486 {
2487 XImage *image, *destimage;
2488 Colormap destcm, srccm;
2489 static const int CACHE_SIZE = 256;
2490
2491 unsigned int i, j;
2492 unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2493 int k, cache_pos, all_cache;
2494
2495 if (!cache || !*cache)
2496 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2497 else
2498 image = *cache;
2499
2500 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2501
2502 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2503 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2504
2505 cache_pos = 0;
2506 all_cache = FALSE;
2507
2508 for (i = 0; i < w; i++)
2509 for (j = 0; j < h; j++) {
2510 unsigned long pixel;
2511 XColor xcol;
2512
2513 pixel = XGetPixel(image, i, j);
2514 for (k = cache_pos; k--; )
2515 if (cachesrc[k] == pixel) {
2516 pixel = cachedest[k];
2517 goto install;
2518 }
2519 if (all_cache)
2520 for (k = CACHE_SIZE; k-- > cache_pos; )
2521 if (cachesrc[k] == pixel) {
2522 pixel = cachedest[k];
2523 goto install;
2524 }
2525
2526 cachesrc[cache_pos] = xcol.pixel = pixel;
2527 XQueryColor(src_display, srccm, &xcol);
2528 if (!XAllocColor(dest_display, destcm, &xcol))
2529 xcol.pixel = 0;
2530 cachedest[cache_pos] = pixel = xcol.pixel;
2531
2532 if (++cache_pos >= CACHE_SIZE) {
2533 cache_pos = 0;
2534 all_cache = TRUE;
2535 }
2536
2537 install:
2538 XPutPixel(destimage, i, j, pixel);
2539 }
2540
2541 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2542 XDestroyImage(destimage);
2543
2544 if (more)
2545 *cache = image;
2546 else
2547 XDestroyImage(image);
2548 }
2549
2550 #if 0
2551
2552 /* Helper function for 16-bit fonts */
2553 static int str16len(const char *s)
2554 {
2555 int count = 0;
2556
2557 while (s[0] && s[1]) {
2558 count++;
2559 s += 2;
2560 }
2561
2562 return count;
2563 }
2564
2565 #endif // 0