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 = (wxX11Dash*) 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 = (wxX11Dash*) 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 wxX11Dash *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 = (wxX11Dash*)m_pen.GetDash();
1323
1324 #if 0
1325 // TODO
1326 if (m_currentStyle == wxSTIPPLE)
1327 m_currentStipple = * m_pen.GetStipple ();
1328 #endif
1329
1330 bool sameStyle = (oldStyle == m_currentStyle &&
1331 oldFill == m_currentFill &&
1332 old_pen_join == m_currentPenJoin &&
1333 old_pen_cap == m_currentPenCap &&
1334 old_pen_nb_dash == m_currentPenDashCount &&
1335 old_pen_dash == m_currentPenDash &&
1336 old_pen_width == m_currentPenWidth);
1337
1338 bool sameColour = (oldPenColour.Ok () &&
1339 (oldPenColour.Red () == m_currentColour.Red ()) &&
1340 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1341 (oldPenColour.Green () == m_currentColour.Green ()) &&
1342 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1343
1344 if (!sameStyle || !GetOptimization())
1345 {
1346 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1347 if (scaled_width < 0)
1348 scaled_width = 0;
1349
1350 int style;
1351 int join;
1352 int cap;
1353 static const wxX11Dash dotted[] = {2, 5};
1354 static const wxX11Dash short_dashed[] = {4, 4};
1355 static const wxX11Dash long_dashed[] = {4, 8};
1356 static const wxX11Dash dotted_dashed[] = {6, 6, 2, 6};
1357
1358 // We express dash pattern in pen width unit, so we are
1359 // independent of zoom factor and so on...
1360 int req_nb_dash;
1361 const wxX11Dash *req_dash;
1362
1363 switch (m_pen.GetStyle ())
1364 {
1365 case wxUSER_DASH:
1366 req_nb_dash = m_currentPenDashCount;
1367 req_dash = m_currentPenDash;
1368 style = LineOnOffDash;
1369 break;
1370 case wxDOT:
1371 req_nb_dash = 2;
1372 req_dash = dotted;
1373 style = LineOnOffDash;
1374 break;
1375 case wxSHORT_DASH:
1376 req_nb_dash = 2;
1377 req_dash = short_dashed;
1378 style = LineOnOffDash;
1379 break;
1380 case wxLONG_DASH:
1381 req_nb_dash = 2;
1382 req_dash = long_dashed;
1383 style = LineOnOffDash;
1384 break;
1385 case wxDOT_DASH:
1386 req_nb_dash = 4;
1387 req_dash = dotted_dashed;
1388 style = LineOnOffDash;
1389 break;
1390 case wxSTIPPLE:
1391 case wxSOLID:
1392 case wxTRANSPARENT:
1393 default:
1394 style = LineSolid;
1395 req_dash = (wxX11Dash*)NULL;
1396 req_nb_dash = 0;
1397 }
1398
1399 if (req_dash && req_nb_dash)
1400 {
1401 wxX11Dash *real_req_dash = new wxX11Dash[req_nb_dash];
1402 if (real_req_dash)
1403 {
1404 int factor = scaled_width == 0 ? 1 : scaled_width;
1405 for (int i = 0; i < req_nb_dash; i++)
1406 real_req_dash[i] = req_dash[i] * factor;
1407 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1408 delete[]real_req_dash;
1409 }
1410 else
1411 {
1412 // No Memory. We use non-scaled dash pattern...
1413 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1414 }
1415 }
1416
1417 switch (m_pen.GetCap ())
1418 {
1419 case wxCAP_PROJECTING:
1420 cap = CapProjecting;
1421 break;
1422 case wxCAP_BUTT:
1423 cap = CapButt;
1424 break;
1425 case wxCAP_ROUND:
1426 default:
1427 cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1428 break;
1429 }
1430
1431 switch (m_pen.GetJoin ())
1432 {
1433 case wxJOIN_BEVEL:
1434 join = JoinBevel;
1435 break;
1436 case wxJOIN_MITER:
1437 join = JoinMiter;
1438 break;
1439 case wxJOIN_ROUND:
1440 default:
1441 join = JoinRound;
1442 break;
1443 }
1444
1445 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1446 }
1447
1448 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1449 {
1450 Pixmap myStipple;
1451
1452 oldStipple = wxNullBitmap; // For later reset!!
1453
1454 switch (m_currentFill)
1455 {
1456 case wxBDIAGONAL_HATCH:
1457 if (bdiag == (Pixmap) 0)
1458 bdiag = XCreateBitmapFromData ((Display*) m_display,
1459 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1460 bdiag_bits, bdiag_width, bdiag_height);
1461 myStipple = bdiag;
1462 break;
1463 case wxFDIAGONAL_HATCH:
1464 if (fdiag == (Pixmap) 0)
1465 fdiag = XCreateBitmapFromData ((Display*) m_display,
1466 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1467 fdiag_bits, fdiag_width, fdiag_height);
1468 myStipple = fdiag;
1469 break;
1470 case wxCROSS_HATCH:
1471 if (cross == (Pixmap) 0)
1472 cross = XCreateBitmapFromData ((Display*) m_display,
1473 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1474 cross_bits, cross_width, cross_height);
1475 myStipple = cross;
1476 break;
1477 case wxHORIZONTAL_HATCH:
1478 if (horiz == (Pixmap) 0)
1479 horiz = XCreateBitmapFromData ((Display*) m_display,
1480 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1481 horiz_bits, horiz_width, horiz_height);
1482 myStipple = horiz;
1483 break;
1484 case wxVERTICAL_HATCH:
1485 if (verti == (Pixmap) 0)
1486 verti = XCreateBitmapFromData ((Display*) m_display,
1487 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1488 verti_bits, verti_width, verti_height);
1489 myStipple = verti;
1490 break;
1491 case wxCROSSDIAG_HATCH:
1492 default:
1493 if (cdiag == (Pixmap) 0)
1494 cdiag = XCreateBitmapFromData ((Display*) m_display,
1495 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1496 cdiag_bits, cdiag_width, cdiag_height);
1497 myStipple = cdiag;
1498 break;
1499 }
1500 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1501 }
1502 else if (m_currentStipple.Ok()
1503 && ((m_currentStipple != oldStipple) || !GetOptimization()))
1504 {
1505 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1506 }
1507
1508 if ((m_currentFill != oldFill) || !GetOptimization())
1509 {
1510 int fill_style;
1511
1512 if (m_currentFill == wxSTIPPLE)
1513 fill_style = FillStippled;
1514 else if (IS_HATCH (m_currentFill))
1515 fill_style = FillStippled;
1516 else
1517 fill_style = FillSolid;
1518 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1519 }
1520
1521 // must test m_logicalFunction, because it involves background!
1522 if (!sameColour || !GetOptimization()
1523 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1524 {
1525 int pixel = -1;
1526 if (m_pen.GetStyle () == wxTRANSPARENT)
1527 pixel = m_backgroundPixel;
1528 else if (!m_colour)
1529 {
1530 unsigned char red = m_pen.GetColour ().Red ();
1531 unsigned char blue = m_pen.GetColour ().Blue ();
1532 unsigned char green = m_pen.GetColour ().Green ();
1533 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1534 && green == (unsigned char) 255)
1535 {
1536 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1537 m_currentColour = *wxWHITE;
1538 m_pen.GetColour().SetPixel(pixel);
1539 m_currentColour.SetPixel(pixel);
1540 }
1541 else
1542 {
1543 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1544 m_currentColour = *wxBLACK;
1545 m_pen.GetColour().SetPixel(pixel);
1546 }
1547 }
1548 else
1549 {
1550 pixel = m_pen.GetColour ().AllocColour(m_display);
1551 m_currentColour.SetPixel(pixel);
1552 }
1553
1554 // Finally, set the GC to the required colour
1555 if (pixel > -1)
1556 {
1557 if (m_logicalFunction == wxXOR)
1558 {
1559 XGCValues values;
1560 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1561 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1562 }
1563 else
1564 {
1565 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1566 }
1567 }
1568 }
1569 else
1570 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1571
1572 m_autoSetting = 0;
1573 }
1574
1575 void wxWindowDC::SetBrush( const wxBrush &brush )
1576 {
1577 wxCHECK_RET( Ok(), "invalid dc" );
1578
1579 m_brush = brush;
1580
1581 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1582 return;
1583
1584 int oldFill = m_currentFill;
1585 wxBitmap oldStipple = m_currentStipple;
1586
1587 m_autoSetting |= 0x1;
1588
1589 m_currentFill = m_brush.GetStyle ();
1590 if (m_currentFill == wxSTIPPLE)
1591 m_currentStipple = * m_brush.GetStipple ();
1592
1593 wxColour oldBrushColour(m_currentColour);
1594 m_currentColour = m_brush.GetColour ();
1595
1596 bool sameColour = (oldBrushColour.Ok () &&
1597 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1598 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1599 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1600 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1601
1602 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1603 {
1604 switch (brush.GetStyle ())
1605 {
1606 case wxTRANSPARENT:
1607 break;
1608 case wxBDIAGONAL_HATCH:
1609 case wxCROSSDIAG_HATCH:
1610 case wxFDIAGONAL_HATCH:
1611 case wxCROSS_HATCH:
1612 case wxHORIZONTAL_HATCH:
1613 case wxVERTICAL_HATCH:
1614 case wxSTIPPLE:
1615 {
1616 // Chris Breeze 23/07/97: use background mode to determine whether
1617 // fill style should be solid or transparent
1618 int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled);
1619 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1620 }
1621 break;
1622 case wxSOLID:
1623 default:
1624 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1625 }
1626 }
1627
1628 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1629 {
1630 Pixmap myStipple;
1631
1632 switch (m_currentFill)
1633 {
1634 case wxBDIAGONAL_HATCH:
1635 if (bdiag == (Pixmap) 0)
1636 bdiag = XCreateBitmapFromData ((Display*) m_display,
1637 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1638 bdiag_bits, bdiag_width, bdiag_height);
1639 myStipple = bdiag;
1640 break;
1641 case wxFDIAGONAL_HATCH:
1642 if (fdiag == (Pixmap) 0)
1643 fdiag = XCreateBitmapFromData ((Display*) m_display,
1644 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1645 fdiag_bits, fdiag_width, fdiag_height);
1646 myStipple = fdiag;
1647 break;
1648 case wxCROSS_HATCH:
1649 if (cross == (Pixmap) 0)
1650 cross = XCreateBitmapFromData ((Display*) m_display,
1651 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1652 cross_bits, cross_width, cross_height);
1653 myStipple = cross;
1654 break;
1655 case wxHORIZONTAL_HATCH:
1656 if (horiz == (Pixmap) 0)
1657 horiz = XCreateBitmapFromData ((Display*) m_display,
1658 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1659 horiz_bits, horiz_width, horiz_height);
1660 myStipple = horiz;
1661 break;
1662 case wxVERTICAL_HATCH:
1663 if (verti == (Pixmap) 0)
1664 verti = XCreateBitmapFromData ((Display*) m_display,
1665 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1666 verti_bits, verti_width, verti_height);
1667 myStipple = verti;
1668 break;
1669 case wxCROSSDIAG_HATCH:
1670 default:
1671 if (cdiag == (Pixmap) 0)
1672 cdiag = XCreateBitmapFromData ((Display*) m_display,
1673 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1674 cdiag_bits, cdiag_width, cdiag_height);
1675 myStipple = cdiag;
1676 break;
1677 }
1678 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1679 }
1680 // X can forget the stipple value when resizing a window (apparently)
1681 // so always set the stipple.
1682 else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1683 {
1684 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1685 }
1686
1687 // must test m_logicalFunction, because it involves background!
1688 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
1689 {
1690 int pixel = -1;
1691 if (!m_colour)
1692 {
1693 // Policy - on a monochrome screen, all brushes are white,
1694 // except when they're REALLY black!!!
1695 unsigned char red = m_brush.GetColour ().Red ();
1696 unsigned char blue = m_brush.GetColour ().Blue ();
1697 unsigned char green = m_brush.GetColour ().Green ();
1698
1699 if (red == (unsigned char) 0 && blue == (unsigned char) 0
1700 && green == (unsigned char) 0)
1701 {
1702 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1703 m_currentColour = *wxBLACK;
1704 m_brush.GetColour().SetPixel(pixel);
1705 m_currentColour.SetPixel(pixel);
1706 }
1707 else
1708 {
1709 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1710 m_currentColour = *wxWHITE;
1711 m_brush.GetColour().SetPixel(pixel);
1712 m_currentColour.SetPixel(pixel);
1713 }
1714
1715 // N.B. comment out the above line and uncomment the following lines
1716 // if you want non-white colours to be black on a monochrome display.
1717 /*
1718 if (red == (unsigned char )255 && blue == (unsigned char)255
1719 && green == (unsigned char)255)
1720 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1721 else
1722 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1723 */
1724 }
1725 else if (m_brush.GetStyle () != wxTRANSPARENT)
1726 {
1727 pixel = m_brush.GetColour().AllocColour(m_display);
1728 m_currentColour.SetPixel(pixel);
1729 }
1730 if (pixel > -1)
1731 {
1732 // Finally, set the GC to the required colour
1733 if (m_logicalFunction == wxXOR)
1734 {
1735 XGCValues values;
1736 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1737 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1738 }
1739 else
1740 {
1741 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1742 }
1743 }
1744 }
1745 else
1746 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
1747 }
1748
1749 void wxWindowDC::SetBackground( const wxBrush &brush )
1750 {
1751 wxCHECK_RET( Ok(), "invalid dc" );
1752
1753 m_backgroundBrush = brush;
1754
1755 if (!m_backgroundBrush.Ok())
1756 return;
1757
1758 int pixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1759
1760 // New behaviour, 10/2/99: setting the background brush of a DC
1761 // doesn't affect the window background colour.
1762 /*
1763 // XSetWindowBackground doesn't work for non-Window pixmaps
1764 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1765 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1766 */
1767
1768 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1769 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1770 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
1771 }
1772
1773 void wxWindowDC::SetLogicalFunction( int function )
1774 {
1775 wxCHECK_RET( Ok(), "invalid dc" );
1776
1777 int x_function;
1778
1779 /* MATTHEW: [9] */
1780 if (m_logicalFunction == function)
1781 return;
1782
1783 switch (function)
1784 {
1785 case wxCLEAR:
1786 x_function = GXclear;
1787 break;
1788 case wxXOR:
1789 x_function = GXxor;
1790 break;
1791 case wxINVERT:
1792 x_function = GXinvert;
1793 break;
1794 case wxOR_REVERSE:
1795 x_function = GXorReverse;
1796 break;
1797 case wxAND_REVERSE:
1798 x_function = GXandReverse;
1799 break;
1800 case wxAND:
1801 x_function = GXand;
1802 break;
1803 case wxOR:
1804 x_function = GXor;
1805 break;
1806 case wxAND_INVERT:
1807 x_function = GXandInverted;
1808 break;
1809 case wxNO_OP:
1810 x_function = GXnoop;
1811 break;
1812 case wxNOR:
1813 x_function = GXnor;
1814 break;
1815 case wxEQUIV:
1816 x_function = GXequiv;
1817 break;
1818 case wxSRC_INVERT:
1819 x_function = GXcopyInverted;
1820 break;
1821 case wxOR_INVERT:
1822 x_function = GXorInverted;
1823 break;
1824 case wxNAND:
1825 x_function = GXnand;
1826 break;
1827 case wxSET:
1828 x_function = GXset;
1829 break;
1830 case wxCOPY:
1831 default:
1832 x_function = GXcopy;
1833 break;
1834 }
1835
1836 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
1837
1838 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
1839 /* MATTHEW: [9] Need to redo pen simply */
1840 m_autoSetting |= 0x2;
1841
1842 m_logicalFunction = function;
1843
1844 }
1845
1846 void wxWindowDC::SetTextForeground( const wxColour &col )
1847 {
1848 wxCHECK_RET( Ok(), "invalid dc" );
1849
1850 if (m_textForegroundColour == col)
1851 return;
1852
1853 m_textForegroundColour = col;
1854
1855 }
1856
1857 void wxWindowDC::SetTextBackground( const wxColour &col )
1858 {
1859 wxCHECK_RET( Ok(), "invalid dc" );
1860
1861 if (m_textBackgroundColour == col)
1862 return;
1863
1864 m_textBackgroundColour = col;
1865 if (!m_textBackgroundColour.Ok())
1866 return;
1867 }
1868
1869 void wxWindowDC::SetBackgroundMode( int mode )
1870 {
1871 m_backgroundMode = mode;
1872 }
1873
1874 void wxWindowDC::SetPalette( const wxPalette& palette )
1875 {
1876 if (m_window)
1877 {
1878 if (palette.Ok())
1879 /* Use GetXColormap */
1880 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1881 (Colormap) palette.GetXColormap());
1882 else
1883 /* Use wxGetMainColormap */
1884 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1885 (Colormap) wxTheApp->GetMainColormap(m_display));
1886 }
1887 }
1888
1889 // Helper function
1890 void wxWindowDC::SetDCClipping()
1891 {
1892 // m_userRegion is the region set by calling SetClippingRegion
1893
1894 if (m_currentRegion)
1895 XDestroyRegion ((Region) m_currentRegion);
1896
1897 // We need to take into account
1898 // clipping imposed on a window by a repaint.
1899 // We'll combine it with the user region. But for now,
1900 // just use the currently-defined user clipping region.
1901 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
1902 m_currentRegion = (WXRegion) XCreateRegion ();
1903 else
1904 m_currentRegion = (WXRegion) NULL;
1905
1906 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
1907 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetX11Region(), (Region) m_userRegion, (Region) m_currentRegion);
1908 else if (m_userRegion)
1909 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
1910 else if (m_window && m_window->GetUpdateRegion().Ok())
1911 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetX11Region(), (Region) m_window->GetUpdateRegion().GetX11Region(),
1912 (Region) m_currentRegion);
1913
1914 if (m_currentRegion)
1915 {
1916 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
1917 }
1918 else
1919 {
1920 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
1921 }
1922
1923 }
1924
1925 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
1926 {
1927 wxDC::DoSetClippingRegion( x, y, width, height );
1928
1929 if (m_userRegion)
1930 XDestroyRegion ((Region) m_userRegion);
1931 m_userRegion = (WXRegion) XCreateRegion ();
1932 XRectangle r;
1933 r.x = XLOG2DEV (x);
1934 r.y = YLOG2DEV (y);
1935 r.width = XLOG2DEVREL(width);
1936 r.height = YLOG2DEVREL(height);
1937 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
1938
1939 SetDCClipping ();
1940 }
1941
1942 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1943 {
1944 wxRect box = region.GetBox();
1945
1946 wxDC::DoSetClippingRegion( box.x, box.y, box.width, box.height );
1947
1948 if (m_userRegion)
1949 XDestroyRegion ((Region) m_userRegion);
1950 m_userRegion = (WXRegion) XCreateRegion ();
1951
1952 XUnionRegion((Region) m_userRegion, (Region) region.GetX11Region(), (Region) m_userRegion);
1953
1954 SetDCClipping ();
1955 }
1956
1957
1958 void wxWindowDC::DestroyClippingRegion()
1959 {
1960 wxDC::DestroyClippingRegion();
1961
1962 if (m_userRegion)
1963 XDestroyRegion ((Region) m_userRegion);
1964 m_userRegion = NULL;
1965
1966 SetDCClipping ();
1967
1968 XGCValues gc_val;
1969 gc_val.clip_mask = None;
1970 }
1971
1972 // Resolution in pixels per logical inch
1973 wxSize wxWindowDC::GetPPI() const
1974 {
1975 return wxSize(100, 100);
1976 }
1977
1978 int wxWindowDC::GetDepth() const
1979 {
1980 // TODO
1981 return 24;
1982 }
1983
1984
1985
1986
1987 // ----------------------------------------------------------------------------
1988 // wxPaintDC
1989 // ----------------------------------------------------------------------------
1990
1991 wxPaintDC::wxPaintDC(wxWindow* win)
1992 : wxWindowDC(win)
1993 {
1994 // TODO clone GTK logic here
1995 }
1996
1997 wxPaintDC::~wxPaintDC()
1998 {
1999 }
2000
2001 // ----------------------------------------------------------------------------
2002 // private functions
2003 // ----------------------------------------------------------------------------
2004
2005 /*
2006 Used when copying between drawables on different (Display*) m_displays. Not
2007 very fast, but better than giving up.
2008 */
2009
2010 static void XCopyRemote(Display *src_display, Display *dest_display,
2011 Drawable src, Drawable dest,
2012 GC destgc,
2013 int srcx, int srcy,
2014 unsigned int w, unsigned int h,
2015 int destx, int desty,
2016 bool more, XImage **cache)
2017 {
2018 XImage *image, *destimage;
2019 Colormap destcm, srccm;
2020 static const int CACHE_SIZE = 256;
2021
2022 unsigned int i, j;
2023 unsigned long cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2024 int k, cache_pos, all_cache;
2025
2026 if (!cache || !*cache)
2027 image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2028 else
2029 image = *cache;
2030
2031 destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2032
2033 srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2034 destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2035
2036 cache_pos = 0;
2037 all_cache = FALSE;
2038
2039 for (i = 0; i < w; i++)
2040 for (j = 0; j < h; j++) {
2041 unsigned long pixel;
2042 XColor xcol;
2043
2044 pixel = XGetPixel(image, i, j);
2045 for (k = cache_pos; k--; )
2046 if (cachesrc[k] == pixel) {
2047 pixel = cachedest[k];
2048 goto install;
2049 }
2050 if (all_cache)
2051 for (k = CACHE_SIZE; k-- > cache_pos; )
2052 if (cachesrc[k] == pixel) {
2053 pixel = cachedest[k];
2054 goto install;
2055 }
2056
2057 cachesrc[cache_pos] = xcol.pixel = pixel;
2058 XQueryColor(src_display, srccm, &xcol);
2059 if (!XAllocColor(dest_display, destcm, &xcol))
2060 xcol.pixel = 0;
2061 cachedest[cache_pos] = pixel = xcol.pixel;
2062
2063 if (++cache_pos >= CACHE_SIZE) {
2064 cache_pos = 0;
2065 all_cache = TRUE;
2066 }
2067
2068 install:
2069 XPutPixel(destimage, i, j, pixel);
2070 }
2071
2072 XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2073 XDestroyImage(destimage);
2074
2075 if (more)
2076 *cache = image;
2077 else
2078 XDestroyImage(image);
2079 }
2080
2081 #if 0
2082
2083 /* Helper function for 16-bit fonts */
2084 static int str16len(const char *s)
2085 {
2086 int count = 0;
2087
2088 while (s[0] && s[1]) {
2089 count++;
2090 s += 2;
2091 }
2092
2093 return count;
2094 }
2095
2096 #endif // 0