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