]> git.saurik.com Git - wxWidgets.git/blob - src/motif/dcclient.cpp
use type safe list instead of wxList for m_columns
[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 {
876 wxCHECK_MSG( Ok(), FALSE, "invalid dc" );
877
878 wxWindowDC* sourceDC = wxDynamicCast(source, wxWindowDC);
879
880 wxASSERT_MSG( sourceDC, "Blit source DC must be wxWindowDC or derived class." );
881
882 // FreeGetPixelCache();
883
884 // Be sure that foreground pixels (1) of the Icon will be painted with pen
885 // colour. [m_pen.SetColour()] Background pixels (0) will be painted with
886 // last selected background color. [::SetBackground]
887 if (m_pen.Ok() && m_autoSetting)
888 SetPen (m_pen);
889
890 // Do bitmap scaling if necessary
891
892 wxBitmap *scaledBitmap = (wxBitmap*) NULL;
893 Pixmap sourcePixmap = (Pixmap) NULL;
894 double scaleX, scaleY;
895 GetUserScale(& scaleX, & scaleY);
896
897 // Sorry, can't scale masks just yet
898 if (!useMask && (scaleX != 1.0 || scaleY != 1.0) && sourceDC->IsKindOf(CLASSINFO(wxMemoryDC)))
899 {
900 wxMemoryDC* memDC = (wxMemoryDC*) sourceDC;
901 wxBitmap& bitmap = memDC->GetBitmap();
902
903 wxASSERT_MSG( (bitmap.Ok()), "Bad source bitmap in wxWindowDC::Blit");
904
905 wxImage image(bitmap);
906 if (!image.Ok())
907 {
908 sourcePixmap = (Pixmap) bitmap.GetPixmap();
909 }
910 else
911 {
912 int scaledW = (int) (bitmap.GetWidth() * scaleX);
913 int scaledH = (int) (bitmap.GetHeight() * scaleY);
914
915 image = image.Scale(scaledW, scaledH);
916 scaledBitmap = new wxBitmap(image.ConvertToBitmap());
917 sourcePixmap = (Pixmap) scaledBitmap->GetPixmap();
918 }
919 }
920 else
921 sourcePixmap = (Pixmap) sourceDC->m_pixmap;
922
923 if (m_pixmap && sourcePixmap)
924 {
925 /* MATTHEW: [9] */
926 int orig = m_logicalFunction;
927
928 SetLogicalFunction (rop);
929
930 if (m_display != sourceDC->m_display)
931 {
932 XImage *cache = NULL;
933
934 if (m_window && m_window->GetBackingPixmap())
935 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display,
936 (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),
937 (GC) m_gcBacking,
938 source->LogicalToDeviceX (xsrc),
939 source->LogicalToDeviceY (ysrc),
940 source->LogicalToDeviceXRel(width),
941 source->LogicalToDeviceYRel(height),
942 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest),
943 TRUE, &cache);
944
945 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
946 {
947 wxMemoryDC *memDC = (wxMemoryDC *)source;
948 wxBitmap& sel = memDC->GetBitmap();
949 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() )
950 {
951 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap());
952 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
953 }
954 }
955
956 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
957 source->LogicalToDeviceX (xsrc),
958 source->LogicalToDeviceY (ysrc),
959 source->LogicalToDeviceXRel(width),
960 source->LogicalToDeviceYRel(height),
961 XLOG2DEV (xdest), YLOG2DEV (ydest),
962 FALSE, &cache);
963
964 if ( useMask )
965 {
966 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
967 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
968 }
969
970 } else
971 {
972 if (m_window && m_window->GetBackingPixmap())
973 {
974 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
975 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetBitmap().GetDepth() == 1)
976 {
977 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
978 source->LogicalToDeviceX (xsrc),
979 source->LogicalToDeviceY (ysrc),
980 source->LogicalToDeviceXRel(width),
981 source->LogicalToDeviceYRel(height),
982 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1);
983 }
984 else
985 {
986 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
987 source->LogicalToDeviceX (xsrc),
988 source->LogicalToDeviceY (ysrc),
989 source->LogicalToDeviceXRel(width),
990 source->LogicalToDeviceYRel(height),
991 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest));
992 }
993 }
994 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
995 {
996 wxMemoryDC *memDC = (wxMemoryDC *)source;
997 wxBitmap& sel = memDC->GetBitmap();
998 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() )
999 {
1000 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap());
1001 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
1002 }
1003 }
1004
1005 // Check if we're copying from a mono bitmap
1006 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) &&
1007 ((wxMemoryDC*)source)->GetBitmap().Ok() && (((wxMemoryDC*)source)->GetBitmap().GetDepth () == 1))
1008 {
1009 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
1010 source->LogicalToDeviceX (xsrc),
1011 source->LogicalToDeviceY (ysrc),
1012 source->LogicalToDeviceXRel(width),
1013 source->LogicalToDeviceYRel(height),
1014 XLOG2DEV (xdest), YLOG2DEV (ydest), 1);
1015 }
1016 else
1017 {
1018 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
1019 source->LogicalToDeviceX (xsrc),
1020 source->LogicalToDeviceY (ysrc),
1021 source->LogicalToDeviceXRel(width),
1022 source->LogicalToDeviceYRel(height),
1023 XLOG2DEV (xdest), YLOG2DEV (ydest));
1024
1025 }
1026 if ( useMask )
1027 {
1028 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
1029 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
1030 }
1031
1032 } /* Remote/local (Display*) m_display */
1033 CalcBoundingBox (xdest, ydest);
1034 CalcBoundingBox (xdest + width, ydest + height);
1035
1036 SetLogicalFunction(orig);
1037
1038 if (scaledBitmap) delete scaledBitmap;
1039
1040 return TRUE;
1041 }
1042 if (scaledBitmap) delete scaledBitmap;
1043
1044 return FALSE;
1045 }
1046
1047 void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1048 {
1049 wxCHECK_RET( Ok(), "invalid dc" );
1050
1051 // Since X draws from the baseline of the text, must add the text height
1052 int cx = 0;
1053 int cy = 0;
1054 int ascent = 0;
1055 int slen;
1056
1057 slen = strlen(text);
1058
1059 if (m_font.Ok())
1060 {
1061 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1062 int direction, descent;
1063 XCharStruct overall_return;
1064 #if 0
1065 if (use16)
1066 (void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction,
1067 &ascent, &descent, &overall_return);
1068 else
1069 #endif // 0
1070 (void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction,
1071 &ascent, &descent, &overall_return);
1072
1073 cx = overall_return.width;
1074 cy = ascent + descent;
1075 }
1076
1077 // First draw a rectangle representing the text background, if a text
1078 // background is specified
1079 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1080 {
1081 wxColour oldPenColour = m_currentColour;
1082 m_currentColour = m_textBackgroundColour;
1083 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1084 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1085 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1086 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1087
1088 // This separation of the big && test required for gcc2.7/HP UX 9.02
1089 // or pixel value can be corrupted!
1090 sameColour = (sameColour &&
1091 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1092
1093 if (!sameColour || !GetOptimization())
1094 {
1095 int pixel = m_textBackgroundColour.AllocColour(m_display);
1096 m_currentColour = m_textBackgroundColour;
1097
1098 // Set the GC to the required colour
1099 if (pixel > -1)
1100 {
1101 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1102 if (m_window && m_window->GetBackingPixmap())
1103 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1104 }
1105 }
1106 else
1107 m_textBackgroundColour = oldPenColour ;
1108
1109 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1110 if (m_window && m_window->GetBackingPixmap())
1111 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1112 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1113 }
1114
1115 // Now set the text foreground and draw the text
1116 if (m_textForegroundColour.Ok ())
1117 {
1118 wxColour oldPenColour = m_currentColour;
1119 m_currentColour = m_textForegroundColour;
1120 bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () &&
1121 (oldPenColour.Red () == m_currentColour.Red ()) &&
1122 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1123 (oldPenColour.Green () == m_currentColour.Green ()) &&
1124 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1125
1126 if (!sameColour || !GetOptimization())
1127 {
1128 int pixel = -1;
1129 if (!m_colour) // Mono display
1130 {
1131 // Unless foreground is really white, draw it in black
1132 unsigned char red = m_textForegroundColour.Red ();
1133 unsigned char blue = m_textForegroundColour.Blue ();
1134 unsigned char green = m_textForegroundColour.Green ();
1135 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1136 && green == (unsigned char) 255)
1137 {
1138 m_currentColour = *wxWHITE;
1139 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1140 m_currentColour.SetPixel(pixel);
1141 m_textForegroundColour.SetPixel(pixel);
1142 }
1143 else
1144 {
1145 m_currentColour = *wxBLACK;
1146 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1147 m_currentColour.SetPixel(pixel);
1148 m_textForegroundColour.SetPixel(pixel);
1149 }
1150 }
1151 else
1152 {
1153 pixel = m_textForegroundColour.AllocColour((Display*) m_display);
1154 m_currentColour.SetPixel(pixel);
1155 }
1156
1157 // Set the GC to the required colour
1158 if (pixel > -1)
1159 {
1160 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1161 if (m_window && m_window->GetBackingPixmap())
1162 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1163 }
1164 }
1165 else
1166 m_textForegroundColour = oldPenColour;
1167 }
1168
1169 // We need to add the ascent, not the whole height, since X draws at the
1170 // point above the descender.
1171 #if 0
1172 if (use16)
1173 XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
1174 (XChar2b *)(char*) (const char*) text, slen);
1175 else
1176 #endif // 0
1177 XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1178
1179 if (m_window && m_window->GetBackingPixmap()) {
1180 #if 0
1181 if (use16)
1182 XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1183 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1184 (XChar2b *)(char*) (const char*) text, slen);
1185 else
1186 #endif // 0
1187 XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1188 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, (char*) (const char*) text, slen);
1189 }
1190
1191 wxCoord w, h;
1192 GetTextExtent (text, &w, &h);
1193 CalcBoundingBox (x + w, y + h);
1194 CalcBoundingBox (x, y);
1195 }
1196
1197 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
1198 {
1199 if (angle == 0.0)
1200 {
1201 DrawText(text, x, y);
1202 return;
1203 }
1204
1205 wxCHECK_RET( Ok(), "invalid dc" );
1206
1207 // Since X draws from the baseline of the text, must add the text height
1208 int cx = 0;
1209 int cy = 0;
1210 int ascent = 0;
1211 int slen;
1212
1213 slen = strlen(text);
1214
1215 if (m_font.Ok())
1216 {
1217 // Calculate text extent.
1218 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1219 int direction, descent;
1220 XCharStruct overall_return;
1221 #if 0
1222 if (use16)
1223 (void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction,
1224 &ascent, &descent, &overall_return);
1225 else
1226 #endif // 0
1227 (void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction,
1228 &ascent, &descent, &overall_return);
1229
1230 cx = overall_return.width;
1231 cy = ascent + descent;
1232 }
1233
1234 wxBitmap src(cx, cy);
1235 wxMemoryDC dc;
1236 dc.SelectObject(src);
1237 dc.SetFont(GetFont());
1238 dc.SetBackground(*wxWHITE_BRUSH);
1239 dc.SetBrush(*wxBLACK_BRUSH);
1240 dc.Clear();
1241 dc.DrawText(text, 0, 0);
1242 dc.SetFont(wxNullFont);
1243
1244 // Calculate the size of the rotated bounding box.
1245 double dx = cos(angle / 180.0 * M_PI);
1246 double dy = sin(angle / 180.0 * M_PI);
1247 double x4 = -cy * dy;
1248 double y4 = cy * dx;
1249 double x3 = cx * dx;
1250 double y3 = cx * dy;
1251 double x2 = x3 + x4;
1252 double y2 = y3 + y4;
1253 double x1 = x;
1254 double y1 = y;
1255
1256 // Create image from the source bitmap after writing the text into it.
1257 wxImage image(src);
1258
1259 int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
1260 int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
1261 int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
1262 int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
1263
1264 // This rotates counterclockwise around the top left corner.
1265 for (int rx = minx; rx < maxx; rx++)
1266 {
1267 for (int ry = miny; ry < maxy; ry++)
1268 {
1269 // transform dest coords to source coords
1270 int sx = (int) (rx * dx + ry * dy + 0.5);
1271 int sy = (int) (ry * dx - rx * dy + 0.5);
1272 if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
1273 {
1274 // draw black pixels, ignore white ones (i.e. transparent b/g)
1275 if (image.GetRed(sx, sy) == 0)
1276 {
1277 DrawPoint((wxCoord) (x1 + maxx - rx), (wxCoord) (cy + y1 - ry));
1278 }
1279 else
1280 {
1281 // Background
1282 //DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
1283 }
1284 }
1285 }
1286 }
1287
1288 #if 0
1289 // First draw a rectangle representing the text background, if a text
1290 // background is specified
1291 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1292 {
1293 wxColour oldPenColour = m_currentColour;
1294 m_currentColour = m_textBackgroundColour;
1295 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1296 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1297 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1298 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1299
1300 // This separation of the big && test required for gcc2.7/HP UX 9.02
1301 // or pixel value can be corrupted!
1302 sameColour = (sameColour &&
1303 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1304
1305 if (!sameColour || !GetOptimization())
1306 {
1307 int pixel = m_textBackgroundColour.AllocColour(m_display);
1308 m_currentColour = m_textBackgroundColour;
1309
1310 // Set the GC to the required colour
1311 if (pixel > -1)
1312 {
1313 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1314 if (m_window && m_window->GetBackingPixmap())
1315 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1316 }
1317 }
1318 else
1319 m_textBackgroundColour = oldPenColour ;
1320
1321 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1322 if (m_window && m_window->GetBackingPixmap())
1323 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1324 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1325 }
1326 #endif
1327
1328 long w, h;
1329 // XXX use pixmap size
1330 GetTextExtent (text, &w, &h);
1331 CalcBoundingBox (x + w, y + h);
1332 CalcBoundingBox (x, y);
1333 }
1334
1335 bool wxWindowDC::CanGetTextExtent() const
1336 {
1337 return TRUE;
1338 }
1339
1340 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1341 wxCoord *descent, wxCoord *externalLeading,
1342 wxFont *font ) const
1343 {
1344 wxCHECK_RET( Ok(), "invalid dc" );
1345
1346 wxFont* theFont = font;
1347 if (!theFont)
1348 theFont = (wxFont *)&m_font; // const_cast
1349
1350 if (!theFont->Ok())
1351 {
1352 // TODO: this should be an error log function
1353 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1354
1355 if (width) *width = -1;
1356 if (height) *height = -1;
1357 return;
1358 }
1359
1360 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1361
1362 int direction, ascent, descent2;
1363 XCharStruct overall;
1364 int slen;
1365
1366 #if 0
1367 if (use16)
1368 slen = str16len(string);
1369 else
1370 #endif // 0
1371 slen = strlen(string);
1372
1373 #if 0
1374 if (use16)
1375 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1376 &ascent, &descent2, &overall);
1377 else
1378 #endif // 0
1379 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1380 &ascent, &descent2, &overall);
1381
1382 if (width) *width = XDEV2LOGREL (overall.width);
1383 if (height) *height = YDEV2LOGREL (ascent + descent2);
1384 if (descent)
1385 *descent = descent2;
1386 if (externalLeading)
1387 *externalLeading = 0;
1388 }
1389
1390 wxCoord wxWindowDC::GetCharWidth() const
1391 {
1392 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1393 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1394
1395 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
1396
1397 int direction, ascent, descent;
1398 XCharStruct overall;
1399 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1400 &descent, &overall);
1401 return XDEV2LOGREL(overall.width);
1402 }
1403
1404 wxCoord wxWindowDC::GetCharHeight() const
1405 {
1406 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1407 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1408
1409 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1410
1411 int direction, ascent, descent;
1412 XCharStruct overall;
1413 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1414 &descent, &overall);
1415 // return XDEV2LOGREL(overall.ascent + overall.descent);
1416 return XDEV2LOGREL(ascent + descent);
1417 }
1418
1419 void wxWindowDC::Clear()
1420 {
1421 wxCHECK_RET( Ok(), "invalid dc" );
1422
1423 int w, h;
1424 if (m_window)
1425 {
1426 m_window->GetSize(&w, &h);
1427
1428 if (m_window && m_window->GetBackingPixmap())
1429 {
1430 w = m_window->GetPixmapWidth();
1431 h = m_window->GetPixmapHeight();
1432 }
1433 }
1434 else
1435 {
1436 if (this->IsKindOf(CLASSINFO(wxMemoryDC)))
1437 {
1438 wxMemoryDC* memDC = (wxMemoryDC*) this;
1439 w = memDC->GetBitmap().GetWidth();
1440 h = memDC->GetBitmap().GetHeight();
1441 }
1442 else
1443 return;
1444 }
1445
1446 wxBrush saveBrush = m_brush;
1447 SetBrush (m_backgroundBrush);
1448
1449 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, 0, w, h);
1450
1451 if (m_window && m_window->GetBackingPixmap())
1452 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 0, 0, w, h);
1453
1454 m_brush = saveBrush;
1455 }
1456
1457 void wxWindowDC::Clear(const wxRect& rect)
1458 {
1459 wxCHECK_RET( Ok(), "invalid dc" );
1460
1461 int x = rect.x; int y = rect.y;
1462 int w = rect.width; int h = rect.height;
1463
1464 wxBrush saveBrush = m_brush;
1465 SetBrush (m_backgroundBrush);
1466
1467 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
1468
1469 if (m_window && m_window->GetBackingPixmap())
1470 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
1471
1472 m_brush = saveBrush;
1473 }
1474
1475 void wxWindowDC::SetFont( const wxFont &font )
1476 {
1477 wxCHECK_RET( Ok(), "invalid dc" );
1478
1479 m_font = font;
1480
1481 if (!m_font.Ok())
1482 {
1483 if ((m_oldFont != (WXFont) 0) && ((wxCoord) m_oldFont != -1))
1484 {
1485 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
1486
1487 if (m_window && m_window->GetBackingPixmap())
1488 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1489 }
1490 return;
1491 }
1492
1493 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1494
1495 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1496 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1497
1498 if (m_window && m_window->GetBackingPixmap())
1499 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
1500 }
1501
1502 void wxWindowDC::SetPen( const wxPen &pen )
1503 {
1504 wxCHECK_RET( Ok(), "invalid dc" );
1505
1506 m_pen = pen;
1507 if (!m_pen.Ok())
1508 return;
1509
1510 wxBitmap oldStipple = m_currentStipple;
1511 int oldStyle = m_currentStyle;
1512 int oldFill = m_currentFill;
1513 int old_pen_width = m_currentPenWidth;
1514 int old_pen_join = m_currentPenJoin;
1515 int old_pen_cap = m_currentPenCap;
1516 int old_pen_nb_dash = m_currentPenDashCount;
1517 wxMOTIFDash *old_pen_dash = m_currentPenDash;
1518
1519 wxColour oldPenColour = m_currentColour;
1520 m_currentColour = m_pen.GetColour ();
1521 m_currentStyle = m_pen.GetStyle ();
1522 m_currentFill = m_pen.GetStyle (); // TODO?
1523 m_currentPenWidth = m_pen.GetWidth ();
1524 m_currentPenJoin = m_pen.GetJoin ();
1525 m_currentPenCap = m_pen.GetCap ();
1526 m_currentPenDashCount = m_pen.GetDashCount();
1527 m_currentPenDash = (wxMOTIFDash*)m_pen.GetDash();
1528
1529 if (m_currentStyle == wxSTIPPLE)
1530 m_currentStipple = * m_pen.GetStipple ();
1531
1532 bool sameStyle = (oldStyle == m_currentStyle &&
1533 oldFill == m_currentFill &&
1534 old_pen_join == m_currentPenJoin &&
1535 old_pen_cap == m_currentPenCap &&
1536 old_pen_nb_dash == m_currentPenDashCount &&
1537 old_pen_dash == m_currentPenDash &&
1538 old_pen_width == m_currentPenWidth);
1539
1540 bool sameColour = (oldPenColour.Ok () &&
1541 (oldPenColour.Red () == m_currentColour.Red ()) &&
1542 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1543 (oldPenColour.Green () == m_currentColour.Green ()) &&
1544 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1545
1546 if (!sameStyle || !GetOptimization())
1547 {
1548 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1549 if (scaled_width < 0)
1550 scaled_width = 0;
1551
1552 int style;
1553 int join;
1554 int cap;
1555 static const wxMOTIFDash dotted[] = {2, 5};
1556 static const wxMOTIFDash short_dashed[] = {4, 4};
1557 static const wxMOTIFDash long_dashed[] = {4, 8};
1558 static const wxMOTIFDash dotted_dashed[] = {6, 6, 2, 6};
1559
1560 // We express dash pattern in pen width unit, so we are
1561 // independent of zoom factor and so on...
1562 int req_nb_dash;
1563 const wxMOTIFDash *req_dash;
1564
1565 switch (m_pen.GetStyle ())
1566 {
1567 case wxUSER_DASH:
1568 req_nb_dash = m_currentPenDashCount;
1569 req_dash = m_currentPenDash;
1570 style = LineOnOffDash;
1571 break;
1572 case wxDOT:
1573 req_nb_dash = 2;
1574 req_dash = dotted;
1575 style = LineOnOffDash;
1576 break;
1577 case wxSHORT_DASH:
1578 req_nb_dash = 2;
1579 req_dash = short_dashed;
1580 style = LineOnOffDash;
1581 break;
1582 case wxLONG_DASH:
1583 req_nb_dash = 2;
1584 req_dash = long_dashed;
1585 style = LineOnOffDash;
1586 break;
1587 case wxDOT_DASH:
1588 req_nb_dash = 4;
1589 req_dash = dotted_dashed;
1590 style = LineOnOffDash;
1591 break;
1592 case wxSTIPPLE:
1593 case wxSOLID:
1594 case wxTRANSPARENT:
1595 default:
1596 style = LineSolid;
1597 req_dash = (wxMOTIFDash*)NULL;
1598 req_nb_dash = 0;
1599 }
1600
1601 if (req_dash && req_nb_dash)
1602 {
1603 wxMOTIFDash *real_req_dash = new wxMOTIFDash[req_nb_dash];
1604 if (real_req_dash)
1605 {
1606 int factor = scaled_width == 0 ? 1 : scaled_width;
1607 for (int i = 0; i < req_nb_dash; i++)
1608 real_req_dash[i] = req_dash[i] * factor;
1609 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1610
1611 if (m_window && m_window->GetBackingPixmap())
1612 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1613 delete[]real_req_dash;
1614 }
1615 else
1616 {
1617 // No Memory. We use non-scaled dash pattern...
1618 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1619
1620 if (m_window && m_window->GetBackingPixmap())
1621 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1622 }
1623 }
1624
1625 switch (m_pen.GetCap ())
1626 {
1627 case wxCAP_PROJECTING:
1628 cap = CapProjecting;
1629 break;
1630 case wxCAP_BUTT:
1631 cap = CapButt;
1632 break;
1633 case wxCAP_ROUND:
1634 default:
1635 cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1636 break;
1637 }
1638
1639 switch (m_pen.GetJoin ())
1640 {
1641 case wxJOIN_BEVEL:
1642 join = JoinBevel;
1643 break;
1644 case wxJOIN_MITER:
1645 join = JoinMiter;
1646 break;
1647 case wxJOIN_ROUND:
1648 default:
1649 join = JoinRound;
1650 break;
1651 }
1652
1653 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1654
1655 if (m_window && m_window->GetBackingPixmap())
1656 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1657 }
1658
1659 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1660 {
1661 Pixmap myStipple;
1662
1663 oldStipple = wxNullBitmap; // For later reset!!
1664
1665 switch (m_currentFill)
1666 {
1667 case wxBDIAGONAL_HATCH:
1668 if (bdiag == (Pixmap) 0)
1669 bdiag = XCreateBitmapFromData ((Display*) m_display,
1670 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1671 bdiag_bits, bdiag_width, bdiag_height);
1672 myStipple = bdiag;
1673 break;
1674 case wxFDIAGONAL_HATCH:
1675 if (fdiag == (Pixmap) 0)
1676 fdiag = XCreateBitmapFromData ((Display*) m_display,
1677 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1678 fdiag_bits, fdiag_width, fdiag_height);
1679 myStipple = fdiag;
1680 break;
1681 case wxCROSS_HATCH:
1682 if (cross == (Pixmap) 0)
1683 cross = XCreateBitmapFromData ((Display*) m_display,
1684 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1685 cross_bits, cross_width, cross_height);
1686 myStipple = cross;
1687 break;
1688 case wxHORIZONTAL_HATCH:
1689 if (horiz == (Pixmap) 0)
1690 horiz = XCreateBitmapFromData ((Display*) m_display,
1691 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1692 horiz_bits, horiz_width, horiz_height);
1693 myStipple = horiz;
1694 break;
1695 case wxVERTICAL_HATCH:
1696 if (verti == (Pixmap) 0)
1697 verti = XCreateBitmapFromData ((Display*) m_display,
1698 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1699 verti_bits, verti_width, verti_height);
1700 myStipple = verti;
1701 break;
1702 case wxCROSSDIAG_HATCH:
1703 default:
1704 if (cdiag == (Pixmap) 0)
1705 cdiag = XCreateBitmapFromData ((Display*) m_display,
1706 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1707 cdiag_bits, cdiag_width, cdiag_height);
1708 myStipple = cdiag;
1709 break;
1710 }
1711 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1712
1713 if (m_window && m_window->GetBackingPixmap())
1714 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1715 }
1716 else if (m_currentStipple.Ok()
1717 && ((m_currentStipple != oldStipple) || !GetOptimization()))
1718 {
1719 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1720
1721 if (m_window && m_window->GetBackingPixmap())
1722 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1723 }
1724
1725 if ((m_currentFill != oldFill) || !GetOptimization())
1726 {
1727 int fill_style;
1728
1729 if (m_currentFill == wxSTIPPLE)
1730 fill_style = FillStippled;
1731 else if (IS_HATCH (m_currentFill))
1732 fill_style = FillStippled;
1733 else
1734 fill_style = FillSolid;
1735 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1736 if (m_window && m_window->GetBackingPixmap())
1737 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1738 }
1739
1740 // must test m_logicalFunction, because it involves background!
1741 if (!sameColour || !GetOptimization()
1742 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1743 {
1744 int pixel = -1;
1745 if (m_pen.GetStyle () == wxTRANSPARENT)
1746 pixel = m_backgroundPixel;
1747 else if (!m_colour)
1748 {
1749 unsigned char red = m_pen.GetColour ().Red ();
1750 unsigned char blue = m_pen.GetColour ().Blue ();
1751 unsigned char green = m_pen.GetColour ().Green ();
1752 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1753 && green == (unsigned char) 255)
1754 {
1755 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1756 m_currentColour = *wxWHITE;
1757 m_pen.GetColour().SetPixel(pixel);
1758 m_currentColour.SetPixel(pixel);
1759 }
1760 else
1761 {
1762 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1763 m_currentColour = *wxBLACK;
1764 m_pen.GetColour().SetPixel(pixel);
1765 }
1766 }
1767 else
1768 {
1769 pixel = m_pen.GetColour ().AllocColour(m_display);
1770 m_currentColour.SetPixel(pixel);
1771 }
1772
1773 // Finally, set the GC to the required colour
1774 if (pixel > -1)
1775 {
1776 if (m_logicalFunction == wxXOR)
1777 {
1778 XGCValues values;
1779 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1780 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1781 if (m_window && m_window->GetBackingPixmap())
1782 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1783 }
1784 else
1785 {
1786 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1787 if (m_window && m_window->GetBackingPixmap())
1788 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1789 }
1790 }
1791 }
1792 else
1793 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1794
1795 m_autoSetting = 0;
1796 }
1797
1798 void wxWindowDC::SetBrush( const wxBrush &brush )
1799 {
1800 wxCHECK_RET( Ok(), "invalid dc" );
1801
1802 m_brush = brush;
1803
1804 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1805 return;
1806
1807 int oldFill = m_currentFill;
1808 wxBitmap oldStipple = m_currentStipple;
1809
1810 m_autoSetting |= 0x1;
1811
1812 m_currentFill = m_brush.GetStyle ();
1813 if (m_currentFill == wxSTIPPLE)
1814 m_currentStipple = * m_brush.GetStipple ();
1815
1816 wxColour oldBrushColour(m_currentColour);
1817 m_currentColour = m_brush.GetColour ();
1818
1819 bool sameColour = (oldBrushColour.Ok () &&
1820 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1821 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1822 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1823 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1824
1825 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1826 {
1827 switch (brush.GetStyle ())
1828 {
1829 case wxTRANSPARENT:
1830 break;
1831 case wxBDIAGONAL_HATCH:
1832 case wxCROSSDIAG_HATCH:
1833 case wxFDIAGONAL_HATCH:
1834 case wxCROSS_HATCH:
1835 case wxHORIZONTAL_HATCH:
1836 case wxVERTICAL_HATCH:
1837 case wxSTIPPLE:
1838 {
1839 // Chris Breeze 23/07/97: use background mode to determine whether
1840 // fill style should be solid or transparent
1841 int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled);
1842 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1843 if (m_window && m_window->GetBackingPixmap())
1844 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1845 }
1846 break;
1847 case wxSOLID:
1848 default:
1849 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1850 if (m_window && m_window->GetBackingPixmap())
1851 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, FillSolid);
1852 }
1853 }
1854
1855 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1856 {
1857 Pixmap myStipple;
1858
1859 switch (m_currentFill)
1860 {
1861 case wxBDIAGONAL_HATCH:
1862 if (bdiag == (Pixmap) 0)
1863 bdiag = XCreateBitmapFromData ((Display*) m_display,
1864 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1865 bdiag_bits, bdiag_width, bdiag_height);
1866 myStipple = bdiag;
1867 break;
1868 case wxFDIAGONAL_HATCH:
1869 if (fdiag == (Pixmap) 0)
1870 fdiag = XCreateBitmapFromData ((Display*) m_display,
1871 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1872 fdiag_bits, fdiag_width, fdiag_height);
1873 myStipple = fdiag;
1874 break;
1875 case wxCROSS_HATCH:
1876 if (cross == (Pixmap) 0)
1877 cross = XCreateBitmapFromData ((Display*) m_display,
1878 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1879 cross_bits, cross_width, cross_height);
1880 myStipple = cross;
1881 break;
1882 case wxHORIZONTAL_HATCH:
1883 if (horiz == (Pixmap) 0)
1884 horiz = XCreateBitmapFromData ((Display*) m_display,
1885 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1886 horiz_bits, horiz_width, horiz_height);
1887 myStipple = horiz;
1888 break;
1889 case wxVERTICAL_HATCH:
1890 if (verti == (Pixmap) 0)
1891 verti = XCreateBitmapFromData ((Display*) m_display,
1892 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1893 verti_bits, verti_width, verti_height);
1894 myStipple = verti;
1895 break;
1896 case wxCROSSDIAG_HATCH:
1897 default:
1898 if (cdiag == (Pixmap) 0)
1899 cdiag = XCreateBitmapFromData ((Display*) m_display,
1900 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1901 cdiag_bits, cdiag_width, cdiag_height);
1902 myStipple = cdiag;
1903 break;
1904 }
1905 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1906
1907 if (m_window && m_window->GetBackingPixmap())
1908 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1909 }
1910 // X can forget the stipple value when resizing a window (apparently)
1911 // so always set the stipple.
1912 else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1913 {
1914 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1915 if (m_window && m_window->GetBackingPixmap())
1916 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1917 }
1918
1919 // must test m_logicalFunction, because it involves background!
1920 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
1921 {
1922 int pixel = -1;
1923 if (!m_colour)
1924 {
1925 // Policy - on a monochrome screen, all brushes are white,
1926 // except when they're REALLY black!!!
1927 unsigned char red = m_brush.GetColour ().Red ();
1928 unsigned char blue = m_brush.GetColour ().Blue ();
1929 unsigned char green = m_brush.GetColour ().Green ();
1930
1931 if (red == (unsigned char) 0 && blue == (unsigned char) 0
1932 && green == (unsigned char) 0)
1933 {
1934 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1935 m_currentColour = *wxBLACK;
1936 m_brush.GetColour().SetPixel(pixel);
1937 m_currentColour.SetPixel(pixel);
1938 }
1939 else
1940 {
1941 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1942 m_currentColour = *wxWHITE;
1943 m_brush.GetColour().SetPixel(pixel);
1944 m_currentColour.SetPixel(pixel);
1945 }
1946
1947 // N.B. comment out the above line and uncomment the following lines
1948 // if you want non-white colours to be black on a monochrome display.
1949 /*
1950 if (red == (unsigned char )255 && blue == (unsigned char)255
1951 && green == (unsigned char)255)
1952 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1953 else
1954 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1955 */
1956 }
1957 else if (m_brush.GetStyle () != wxTRANSPARENT)
1958 {
1959 pixel = m_brush.GetColour().AllocColour(m_display);
1960 m_currentColour.SetPixel(pixel);
1961 }
1962 if (pixel > -1)
1963 {
1964 // Finally, set the GC to the required colour
1965 if (m_logicalFunction == wxXOR)
1966 {
1967 XGCValues values;
1968 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1969 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1970 if (m_window && m_window->GetBackingPixmap())
1971 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1972 }
1973 else
1974 {
1975 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1976 if (m_window && m_window->GetBackingPixmap())
1977 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1978 }
1979 }
1980 }
1981 else
1982 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
1983 }
1984
1985 void wxWindowDC::SetBackground( const wxBrush &brush )
1986 {
1987 wxCHECK_RET( Ok(), "invalid dc" );
1988
1989 m_backgroundBrush = brush;
1990
1991 if (!m_backgroundBrush.Ok())
1992 return;
1993
1994 int pixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1995
1996 // New behaviour, 10/2/99: setting the background brush of a DC
1997 // doesn't affect the window background colour.
1998 /*
1999 // XSetWindowBackground doesn't work for non-Window pixmaps
2000 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
2001 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
2002 */
2003
2004 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
2005 // And Blit,... (Any fct that use XCopyPlane, in fact.)
2006 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
2007 if (m_window && m_window->GetBackingPixmap())
2008 XSetBackground ((Display*) m_display,(GC) m_gcBacking, pixel);
2009 }
2010
2011 void wxWindowDC::SetLogicalFunction( int function )
2012 {
2013 wxCHECK_RET( Ok(), "invalid dc" );
2014
2015 int x_function;
2016
2017 /* MATTHEW: [9] */
2018 if (m_logicalFunction == function)
2019 return;
2020
2021 switch (function)
2022 {
2023 case wxCLEAR:
2024 x_function = GXclear;
2025 break;
2026 case wxXOR:
2027 x_function = GXxor;
2028 break;
2029 case wxINVERT:
2030 x_function = GXinvert;
2031 break;
2032 case wxOR_REVERSE:
2033 x_function = GXorReverse;
2034 break;
2035 case wxAND_REVERSE:
2036 x_function = GXandReverse;
2037 break;
2038 case wxAND:
2039 x_function = GXand;
2040 break;
2041 case wxOR:
2042 x_function = GXor;
2043 break;
2044 case wxAND_INVERT:
2045 x_function = GXandInverted;
2046 break;
2047 case wxNO_OP:
2048 x_function = GXnoop;
2049 break;
2050 case wxNOR:
2051 x_function = GXnor;
2052 break;
2053 case wxEQUIV:
2054 x_function = GXequiv;
2055 break;
2056 case wxSRC_INVERT:
2057 x_function = GXcopyInverted;
2058 break;
2059 case wxOR_INVERT:
2060 x_function = GXorInverted;
2061 break;
2062 case wxNAND:
2063 x_function = GXnand;
2064 break;
2065 case wxSET:
2066 x_function = GXset;
2067 break;
2068 case wxCOPY:
2069 default:
2070 x_function = GXcopy;
2071 break;
2072 }
2073
2074 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
2075 if (m_window && m_window->GetBackingPixmap())
2076 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
2077
2078 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
2079 /* MATTHEW: [9] Need to redo pen simply */
2080 m_autoSetting |= 0x2;
2081
2082 m_logicalFunction = function;
2083
2084 }
2085
2086 void wxWindowDC::SetTextForeground( const wxColour &col )
2087 {
2088 wxCHECK_RET( Ok(), "invalid dc" );
2089
2090 if (m_textForegroundColour == col)
2091 return;
2092
2093 m_textForegroundColour = col;
2094
2095 }
2096
2097 void wxWindowDC::SetTextBackground( const wxColour &col )
2098 {
2099 wxCHECK_RET( Ok(), "invalid dc" );
2100
2101 if (m_textBackgroundColour == col)
2102 return;
2103
2104 m_textBackgroundColour = col;
2105 if (!m_textBackgroundColour.Ok())
2106 return;
2107 }
2108
2109 void wxWindowDC::SetBackgroundMode( int mode )
2110 {
2111 m_backgroundMode = mode;
2112 }
2113
2114 void wxWindowDC::SetPalette( const wxPalette& palette )
2115 {
2116 if (m_window)
2117 {
2118 if (palette.Ok())
2119 /* Use GetXColormap */
2120 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2121 (Colormap) palette.GetXColormap());
2122 else
2123 /* Use wxGetMainColormap */
2124 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2125 (Colormap) wxTheApp->GetMainColormap(m_display));
2126 }
2127 }
2128
2129 // Helper function
2130 void wxWindowDC::SetDCClipping()
2131 {
2132 // m_userRegion is the region set by calling SetClippingRegion
2133
2134 if (m_currentRegion)
2135 XDestroyRegion ((Region) m_currentRegion);
2136
2137 // We need to take into account
2138 // clipping imposed on a window by a repaint.
2139 // We'll combine it with the user region. But for now,
2140 // just use the currently-defined user clipping region.
2141 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
2142 m_currentRegion = (WXRegion) XCreateRegion ();
2143 else
2144 m_currentRegion = (WXRegion) NULL;
2145
2146 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2147 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
2148 else if (m_userRegion)
2149 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
2150 else if (m_window && m_window->GetUpdateRegion().Ok())
2151 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
2152 (Region) m_currentRegion);
2153
2154 if (m_currentRegion)
2155 {
2156 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
2157 }
2158 else
2159 {
2160 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2161 }
2162
2163 }
2164
2165 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
2166 {
2167 wxDC::DoSetClippingRegion( x, y, width, height );
2168
2169 if (m_userRegion)
2170 XDestroyRegion ((Region) m_userRegion);
2171 m_userRegion = (WXRegion) XCreateRegion ();
2172 XRectangle r;
2173 r.x = XLOG2DEV (x);
2174 r.y = YLOG2DEV (y);
2175 r.width = XLOG2DEVREL(width);
2176 r.height = YLOG2DEVREL(height);
2177 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
2178
2179 SetDCClipping ();
2180
2181 // Needs to work differently for Pixmap: without this,
2182 // there's a nasty (Display*) m_display bug. 8/12/94
2183 if (m_window && m_window->GetBackingPixmap())
2184 {
2185 XRectangle rects[1];
2186 rects[0].x = XLOG2DEV_2(x);
2187 rects[0].y = YLOG2DEV_2(y);
2188 rects[0].width = XLOG2DEVREL(width);
2189 rects[0].height = YLOG2DEVREL(height);
2190 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2191 }
2192 }
2193
2194 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2195 {
2196 wxRect box = region.GetBox();
2197
2198 wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height );
2199
2200 if (m_userRegion)
2201 XDestroyRegion ((Region) m_userRegion);
2202 m_userRegion = (WXRegion) XCreateRegion ();
2203
2204 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
2205
2206 SetDCClipping ();
2207
2208 // Needs to work differently for Pixmap: without this,
2209 // there's a nasty (Display*) m_display bug. 8/12/94
2210 if (m_window && m_window->GetBackingPixmap())
2211 {
2212 XRectangle rects[1];
2213 rects[0].x = XLOG2DEV_2(box.x);
2214 rects[0].y = YLOG2DEV_2(box.y);
2215 rects[0].width = XLOG2DEVREL(box.width);
2216 rects[0].height = YLOG2DEVREL(box.height);
2217 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2218 }
2219 }
2220
2221
2222 void wxWindowDC::DestroyClippingRegion()
2223 {
2224 wxDC::DestroyClippingRegion();
2225
2226 if (m_userRegion)
2227 XDestroyRegion ((Region) m_userRegion);
2228 m_userRegion = NULL;
2229
2230 SetDCClipping ();
2231
2232 XGCValues gc_val;
2233 gc_val.clip_mask = None;
2234 if (m_window && m_window->GetBackingPixmap())
2235 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
2236 }
2237
2238 // Resolution in pixels per logical inch
2239 wxSize wxWindowDC::GetPPI() const
2240 {
2241 return wxSize(100, 100);
2242 }
2243
2244 int wxWindowDC::GetDepth() const
2245 {
2246 // TODO
2247 return 24;
2248 }
2249
2250
2251
2252
2253 // ----------------------------------------------------------------------------
2254 // wxPaintDC
2255 // ----------------------------------------------------------------------------
2256
2257 wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win)
2258 {
2259 wxRegion* region = NULL;
2260
2261 // Combine all the update rects into a region
2262 const wxRectList& updateRects(win->GetUpdateRects());
2263 if ( updateRects.GetCount() != 0 )
2264 {
2265 for ( wxRectList::Node *node = updateRects.GetFirst();
2266 node;
2267 node = node->GetNext() )
2268 {
2269 wxRect* rect = node->GetData();
2270
2271 if (!region)
2272 region = new wxRegion(*rect);
2273 else
2274 // TODO: is this correct? In SetDCClipping above,
2275 // XIntersectRegion is used to combine paint and user
2276 // regions. XIntersectRegion appears to work in that case...
2277 region->Union(*rect);
2278 }
2279 }
2280 else
2281 {
2282 int cw, ch;
2283 win->GetClientSize(&cw, &ch);
2284 region = new wxRegion(wxRect(0, 0, cw, ch));
2285 }
2286
2287 win->SetUpdateRegion(*region);
2288
2289 wxRegion& theRegion(win->GetUpdateRegion());
2290 theRegion.SetRects(updateRects); // We also store in terms of rects, for iteration to work.
2291
2292 // Set the clipping region. Any user-defined region will be combined with this
2293 // one in SetDCClipping.
2294 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
2295
2296 delete region;
2297 }
2298
2299 wxPaintDC::~wxPaintDC()
2300 {
2301 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2302 if (m_window)
2303 m_window->ClearUpdateRegion();
2304 }
2305
2306 // ----------------------------------------------------------------------------
2307 // private functions
2308 // ----------------------------------------------------------------------------
2309
2310 /*
2311 Used when copying between drawables on different (Display*) m_displays. Not
2312 very fast, but better than giving up.
2313 */
2314
2315 static void XCopyRemote(Display *src_display, Display *dest_display,
2316 Drawable src, Drawable dest,
2317 GC destgc,
2318 int srcx, int srcy,
2319 unsigned int w, unsigned int h,
2320 int destx, int desty,
2321 bool more, XImage **cache)
2322 {
2323 XImage *image, *destimage;
2324 Colormap destcm, srccm;
2325 static const int CACHE_SIZE = 256;
2326
2327 unsigned int i, j;
2328 unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2329 int k, cache_pos, all_cache;
2330
2331 if (!cache || !*cache)
2332 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2333 else
2334 image = *cache;
2335
2336 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2337
2338 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2339 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2340
2341 cache_pos = 0;
2342 all_cache = FALSE;
2343
2344 for (i = 0; i < w; i++)
2345 for (j = 0; j < h; j++) {
2346 unsigned long pixel;
2347 XColor xcol;
2348
2349 pixel = XGetPixel(image, i, j);
2350 for (k = cache_pos; k--; )
2351 if (cachesrc[k] == pixel) {
2352 pixel = cachedest[k];
2353 goto install;
2354 }
2355 if (all_cache)
2356 for (k = CACHE_SIZE; k-- > cache_pos; )
2357 if (cachesrc[k] == pixel) {
2358 pixel = cachedest[k];
2359 goto install;
2360 }
2361
2362 cachesrc[cache_pos] = xcol.pixel = pixel;
2363 XQueryColor(src_display, srccm, &xcol);
2364 if (!XAllocColor(dest_display, destcm, &xcol))
2365 xcol.pixel = 0;
2366 cachedest[cache_pos] = pixel = xcol.pixel;
2367
2368 if (++cache_pos >= CACHE_SIZE) {
2369 cache_pos = 0;
2370 all_cache = TRUE;
2371 }
2372
2373 install:
2374 XPutPixel(destimage, i, j, pixel);
2375 }
2376
2377 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2378 XDestroyImage(destimage);
2379
2380 if (more)
2381 *cache = image;
2382 else
2383 XDestroyImage(image);
2384 }
2385
2386 #if 0
2387
2388 /* Helper function for 16-bit fonts */
2389 static int str16len(const char *s)
2390 {
2391 int count = 0;
2392
2393 while (s[0] && s[1]) {
2394 count++;
2395 s += 2;
2396 }
2397
2398 return count;
2399 }
2400
2401 #endif // 0