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