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