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