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