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