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