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