Implemented DoBlit().
[wxWidgets.git] / src / x11 / dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: Julian Smart, Robert Roebling
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart, Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "dcclient.h"
14 #endif
15
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
18 #include "wx/window.h"
19 #include "wx/app.h"
20 #include "wx/image.h"
21
22 #include "wx/x11/private.h"
23
24 #include <math.h>
25
26 //-----------------------------------------------------------------------------
27 // local defines
28 //-----------------------------------------------------------------------------
29
30 #define USE_PAINT_REGION 1
31
32 //-----------------------------------------------------------------------------
33 // local data
34 //-----------------------------------------------------------------------------
35
36 #include "bdiag.xbm"
37 #include "fdiag.xbm"
38 #include "cdiag.xbm"
39 #include "horiz.xbm"
40 #include "verti.xbm"
41 #include "cross.xbm"
42 #define num_hatches 6
43
44 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
45 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
46
47 static Pixmap hatches[num_hatches];
48 static Pixmap *hatch_bitmap = (Pixmap *) NULL;
49
50 //-----------------------------------------------------------------------------
51 // constants
52 //-----------------------------------------------------------------------------
53
54 const double RAD2DEG = 180.0 / M_PI;
55
56 // ----------------------------------------------------------------------------
57 // private functions
58 // ----------------------------------------------------------------------------
59
60 static inline double dmax(double a, double b) { return a > b ? a : b; }
61 static inline double dmin(double a, double b) { return a < b ? a : b; }
62
63 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
64
65 //-----------------------------------------------------------------------------
66 // Implement Pool of Graphic contexts. Creating them takes too much time.
67 //-----------------------------------------------------------------------------
68
69 #define GC_POOL_SIZE 200
70
71 enum wxPoolGCType
72 {
73 wxGC_ERROR = 0,
74 wxTEXT_MONO,
75 wxBG_MONO,
76 wxPEN_MONO,
77 wxBRUSH_MONO,
78 wxTEXT_COLOUR,
79 wxBG_COLOUR,
80 wxPEN_COLOUR,
81 wxBRUSH_COLOUR,
82 wxTEXT_SCREEN,
83 wxBG_SCREEN,
84 wxPEN_SCREEN,
85 wxBRUSH_SCREEN
86 };
87
88 struct wxGC
89 {
90 GC m_gc;
91 wxPoolGCType m_type;
92 bool m_used;
93 };
94
95 static wxGC wxGCPool[GC_POOL_SIZE];
96
97 static void wxInitGCPool()
98 {
99 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) );
100 }
101
102 static void wxCleanUpGCPool()
103 {
104 for (int i = 0; i < GC_POOL_SIZE; i++)
105 {
106 if (wxGCPool[i].m_gc)
107 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc );
108 }
109 }
110
111 static GC wxGetPoolGC( Window window, wxPoolGCType type )
112 {
113 for (int i = 0; i < GC_POOL_SIZE; i++)
114 {
115 if (!wxGCPool[i].m_gc)
116 {
117 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL );
118 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE );
119 wxGCPool[i].m_type = type;
120 wxGCPool[i].m_used = FALSE;
121 }
122 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
123 {
124 wxGCPool[i].m_used = TRUE;
125 return wxGCPool[i].m_gc;
126 }
127 }
128
129 wxFAIL_MSG( wxT("No GC available") );
130
131 return (GC) NULL;
132 }
133
134 static void wxFreePoolGC( GC gc )
135 {
136 for (int i = 0; i < GC_POOL_SIZE; i++)
137 {
138 if (wxGCPool[i].m_gc == gc)
139 {
140 wxGCPool[i].m_used = FALSE;
141 return;
142 }
143 }
144
145 wxFAIL_MSG( wxT("Wrong GC") );
146 }
147
148 // ----------------------------------------------------------------------------
149 // wxWindowDC
150 // ----------------------------------------------------------------------------
151
152 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
153
154 wxWindowDC::wxWindowDC()
155 {
156 m_display = (WXDisplay *) NULL;
157 m_penGC = (WXGC *) NULL;
158 m_brushGC = (WXGC *) NULL;
159 m_textGC = (WXGC *) NULL;
160 m_bgGC = (WXGC *) NULL;
161 m_cmap = (WXColormap *) NULL;
162 m_isMemDC = FALSE;
163 m_isScreenDC = FALSE;
164 m_owner = (wxWindow *)NULL;
165 }
166
167 wxWindowDC::wxWindowDC( wxWindow *window )
168 {
169 wxASSERT_MSG( window, wxT("DC needs a window") );
170
171 m_display = (WXDisplay *) NULL;
172 m_penGC = (WXGC *) NULL;
173 m_brushGC = (WXGC *) NULL;
174 m_textGC = (WXGC *) NULL;
175 m_bgGC = (WXGC *) NULL;
176 m_cmap = (WXColormap *) NULL;
177 m_owner = (wxWindow *)NULL;
178 m_isMemDC = FALSE;
179 m_isScreenDC = FALSE;
180 m_font = window->GetFont();
181
182 m_window = (WXWindow*) window->GetMainWindow();
183
184 // not realized ?
185 if (!m_window)
186 {
187 // don't report problems
188 m_ok = TRUE;
189
190 return;
191 }
192
193 m_display = (WXDisplay *) wxGlobalDisplay();
194
195 int screen = DefaultScreen( (Display*) m_display );
196 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
197
198 SetUpDC();
199
200 /* this must be done after SetUpDC, bacause SetUpDC calls the
201 repective SetBrush, SetPen, SetBackground etc functions
202 to set up the DC. SetBackground call m_owner->SetBackground
203 and this might not be desired as the standard dc background
204 is white whereas a window might assume gray to be the
205 standard (as e.g. wxStatusBar) */
206
207 m_owner = window;
208 }
209
210 wxWindowDC::~wxWindowDC()
211 {
212 Destroy();
213 }
214
215 void wxWindowDC::SetUpDC()
216 {
217 m_ok = TRUE;
218
219 wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
220
221 if (m_isScreenDC)
222 {
223 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_SCREEN );
224 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_SCREEN );
225 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN );
226 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN );
227 }
228 else
229 if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1))
230 {
231 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_MONO );
232 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_MONO );
233 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO );
234 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO );
235 }
236 else
237 {
238 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR );
239 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_COLOUR );
240 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_COLOUR );
241 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_COLOUR );
242 }
243
244 /* background colour */
245 m_backgroundBrush = *wxWHITE_BRUSH;
246 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
247 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel();
248
249 /* m_textGC */
250 m_textForegroundColour.CalcPixel( m_cmap );
251 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
252
253 m_textBackgroundColour.CalcPixel( m_cmap );
254 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
255
256 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid );
257
258 #if wxUSE_NANOX
259 // By default, draw transparently
260 GrSetGCUseBackground((GC) m_textGC, FALSE);
261 #endif
262
263 /* m_penGC */
264 m_pen.GetColour().CalcPixel( m_cmap );
265 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
266 XSetBackground( (Display*) m_display, (GC) m_penGC, bg_col );
267
268 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, 0, LineSolid, CapNotLast, JoinRound );
269
270 /* m_brushGC */
271 m_brush.GetColour().CalcPixel( m_cmap );
272 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
273 XSetBackground( (Display*) m_display, (GC) m_brushGC, bg_col );
274
275 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
276
277 /* m_bgGC */
278 XSetForeground( (Display*) m_display, (GC) m_bgGC, bg_col );
279 XSetBackground( (Display*) m_display, (GC) m_bgGC, bg_col );
280
281 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
282
283 /* ROPs */
284 XSetFunction( (Display*) m_display, (GC) m_textGC, GXcopy );
285 XSetFunction( (Display*) m_display, (GC) m_brushGC, GXcopy );
286 XSetFunction( (Display*) m_display, (GC)m_penGC, GXcopy );
287
288 /* clipping */
289 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
290 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
291 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
292 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
293
294 if (!hatch_bitmap)
295 {
296 int xscreen = DefaultScreen( (Display*) m_display );
297 Window xroot = RootWindow( (Display*) m_display, xscreen );
298
299 hatch_bitmap = hatches;
300 hatch_bitmap[0] = XCreateBitmapFromData( (Display*) m_display, xroot, bdiag_bits, bdiag_width, bdiag_height );
301 hatch_bitmap[1] = XCreateBitmapFromData( (Display*) m_display, xroot, cdiag_bits, cdiag_width, cdiag_height );
302 hatch_bitmap[2] = XCreateBitmapFromData( (Display*) m_display, xroot, fdiag_bits, fdiag_width, fdiag_height );
303 hatch_bitmap[3] = XCreateBitmapFromData( (Display*) m_display, xroot, cross_bits, cross_width, cross_height );
304 hatch_bitmap[4] = XCreateBitmapFromData( (Display*) m_display, xroot, horiz_bits, horiz_width, horiz_height );
305 hatch_bitmap[5] = XCreateBitmapFromData( (Display*) m_display, xroot, verti_bits, verti_width, verti_height );
306 }
307 }
308
309 void wxWindowDC::DoGetSize( int* width, int* height ) const
310 {
311 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
312
313 m_owner->GetSize(width, height);
314 }
315
316 void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
317 const wxColour& WXUNUSED(col), int WXUNUSED(style) )
318 {
319 wxFAIL_MSG("not implemented");
320 }
321
322 bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
323 {
324 // Generic (and therefore rather inefficient) method.
325 // Could be improved.
326 wxMemoryDC memdc;
327 wxBitmap bitmap(1, 1);
328 memdc.SelectObject(bitmap);
329 memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
330 memdc.SelectObject(wxNullBitmap);
331 wxImage image(bitmap);
332 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
333 return TRUE;
334 }
335
336 void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
337 {
338 wxCHECK_RET( Ok(), wxT("invalid window dc") );
339
340 if (m_pen.GetStyle() != wxTRANSPARENT)
341 {
342 if (m_window)
343 XDrawLine( (Display*) m_display, (Window) m_window,
344 (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
345
346 CalcBoundingBox(x1, y1);
347 CalcBoundingBox(x2, y2);
348 }
349 }
350
351 void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
352 {
353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
354
355 if (m_pen.GetStyle() != wxTRANSPARENT)
356 {
357 int w = 0;
358 int h = 0;
359 GetSize( &w, &h );
360 wxCoord xx = XLOG2DEV(x);
361 wxCoord yy = YLOG2DEV(y);
362 if (m_window)
363 {
364 XDrawLine( (Display*) m_display, (Window) m_window,
365 (GC) m_penGC, 0, yy, XLOG2DEVREL(w), yy );
366 XDrawLine( (Display*) m_display, (Window) m_window,
367 (GC) m_penGC, xx, 0, xx, YLOG2DEVREL(h) );
368 }
369 }
370 }
371
372 void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
373 {
374 wxCHECK_RET( Ok(), wxT("invalid window dc") );
375
376 wxCoord xx1 = XLOG2DEV(x1);
377 wxCoord yy1 = YLOG2DEV(y1);
378 wxCoord xx2 = XLOG2DEV(x2);
379 wxCoord yy2 = YLOG2DEV(y2);
380 wxCoord xxc = XLOG2DEV(xc);
381 wxCoord yyc = YLOG2DEV(yc);
382 double dx = xx1 - xxc;
383 double dy = yy1 - yyc;
384 double radius = sqrt((double)(dx*dx+dy*dy));
385 wxCoord r = (wxCoord)radius;
386 double radius1, radius2;
387
388 if (xx1 == xx2 && yy1 == yy2)
389 {
390 radius1 = 0.0;
391 radius2 = 360.0;
392 }
393 else
394 if (radius == 0.0)
395 {
396 radius1 = radius2 = 0.0;
397 }
398 else
399 {
400 radius1 = (xx1 - xxc == 0) ?
401 (yy1 - yyc < 0) ? 90.0 : -90.0 :
402 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
403 radius2 = (xx2 - xxc == 0) ?
404 (yy2 - yyc < 0) ? 90.0 : -90.0 :
405 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
406 }
407 wxCoord alpha1 = wxCoord(radius1 * 64.0);
408 wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0);
409 while (alpha2 <= 0) alpha2 += 360*64;
410 while (alpha1 > 360*64) alpha1 -= 360*64;
411
412 if (m_window)
413 {
414 if (m_brush.GetStyle() != wxTRANSPARENT)
415 {
416 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
417 {
418 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
419 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
420 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
421
422 XFillArc( (Display*) m_display, (Window) m_window,
423 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
424
425 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
426 } else
427 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
428 {
429 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
430 m_deviceOriginX % 15, m_deviceOriginY % 15 );
431
432 XFillArc( (Display*) m_display, (Window) m_window,
433 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
434
435 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
436 } else
437 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
438 {
439 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
440 m_deviceOriginX % 16, m_deviceOriginY % 16 );
441
442 XFillArc( (Display*) m_display, (Window) m_window,
443 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
444
445 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
446 } else
447 if (m_brush.GetStyle() == wxSTIPPLE)
448 {
449 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
450 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
451 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
452
453 XFillArc( (Display*) m_display, (Window) m_window,
454 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
455
456 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
457 }
458 else
459 {
460 XFillArc( (Display*) m_display, (Window) m_window,
461 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
462 }
463 }
464
465 if (m_pen.GetStyle() != wxTRANSPARENT)
466 {
467 XDrawArc( (Display*) m_display, (Window) m_window,
468 (GC) m_penGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
469
470 XDrawLine( (Display*) m_display, (Window) m_window,
471 (GC) m_penGC, xx1, yy1, xxc, yyc );
472
473 XDrawLine( (Display*) m_display, (Window) m_window,
474 (GC) m_penGC, xxc, yyc, xx2, yy2 );
475 }
476 }
477
478 CalcBoundingBox (x1, y1);
479 CalcBoundingBox (x2, y2);
480 }
481
482 void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
483 {
484 wxCHECK_RET( Ok(), wxT("invalid window dc") );
485
486 wxCoord xx = XLOG2DEV(x);
487 wxCoord yy = YLOG2DEV(y);
488 wxCoord ww = m_signX * XLOG2DEVREL(width);
489 wxCoord hh = m_signY * YLOG2DEVREL(height);
490
491 // CMB: handle -ve width and/or height
492 if (ww < 0) { ww = -ww; xx = xx - ww; }
493 if (hh < 0) { hh = -hh; yy = yy - hh; }
494
495 if (m_window)
496 {
497 wxCoord start = wxCoord(sa * 64.0);
498 wxCoord end = wxCoord((ea-sa) * 64.0);
499
500 if (m_brush.GetStyle() != wxTRANSPARENT)
501 {
502 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
503 {
504 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
505 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
506 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
507
508 XFillArc( (Display*) m_display, (Window) m_window,
509 (GC) m_textGC, xx, yy, ww, hh, start, end );
510
511 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
512 } else
513 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
514 {
515 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
516 m_deviceOriginX % 15, m_deviceOriginY % 15 );
517
518 XFillArc( (Display*) m_display, (Window) m_window,
519 (GC) m_brushGC, xx, yy, ww, hh, start, end );
520
521 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
522 } else
523 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
524 {
525 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
526 m_deviceOriginX % 16, m_deviceOriginY % 16 );
527
528 XFillArc( (Display*) m_display, (Window) m_window,
529 (GC) m_brushGC, xx, yy, ww, hh, start, end );
530
531 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
532 } else
533 if (m_brush.GetStyle() == wxSTIPPLE)
534 {
535 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
536 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
537 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
538
539 XFillArc( (Display*) m_display, (Window) m_window,
540 (GC) m_brushGC, xx, yy, ww, hh, start, end );
541
542 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
543 }
544 else
545 {
546 XFillArc( (Display*) m_display, (Window) m_window,
547 (GC) m_brushGC, xx, yy, ww, hh, start, end );
548 }
549 }
550
551 if (m_pen.GetStyle() != wxTRANSPARENT)
552 {
553 XDrawArc( (Display*) m_display, (Window) m_window,
554 (GC) m_penGC, xx, yy, ww, hh, start, end );
555 }
556 }
557
558 CalcBoundingBox (x, y);
559 CalcBoundingBox (x + width, y + height);
560 }
561
562 void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
563 {
564 wxCHECK_RET( Ok(), wxT("invalid window dc") );
565
566 if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window)
567 XDrawPoint( (Display*) m_display, (Window) m_window,
568 (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
569
570 CalcBoundingBox (x, y);
571 }
572
573 void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
574 {
575 wxCHECK_RET( Ok(), wxT("invalid window dc") );
576
577 if (m_pen.GetStyle() == wxTRANSPARENT) return;
578 if (n <= 0) return;
579
580 XPoint *xpoints = new XPoint[n];
581 for (int i = 0; i < n; i++)
582 {
583 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
584 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
585
586 CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset );
587 }
588 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n, 0 );
589
590 delete[] xpoints;
591 }
592
593 void wxWindowDC::DoDrawPolygon( int n, wxPoint points[],
594 wxCoord xoffset, wxCoord yoffset, int fillStyle )
595 {
596 wxCHECK_RET( Ok(), wxT("invalid window dc") );
597
598 if (n <= 0) return;
599
600 XPoint *xpoints = new XPoint[n + 1];
601 int i;
602 for (i = 0; i < n; i++)
603 {
604 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
605 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
606
607 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
608 }
609
610 if (m_window)
611 {
612 if (m_brush.GetStyle() != wxTRANSPARENT)
613 {
614
615 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
616 {
617 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
618 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
619 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
620
621 XFillPolygon( (Display*) m_display, (Window) m_window,
622 (GC) m_textGC, xpoints, n, Complex, 0);
623
624 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
625 } else
626 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
627 {
628 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
629 m_deviceOriginX % 15, m_deviceOriginY % 15 );
630
631 XFillPolygon( (Display*) m_display, (Window) m_window,
632 (GC) m_brushGC, xpoints, n, Complex, 0);
633
634 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
635 } else
636 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
637 {
638 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
639 m_deviceOriginX % 16, m_deviceOriginY % 16 );
640
641 XFillPolygon( (Display*) m_display, (Window) m_window,
642 (GC) m_brushGC, xpoints, n, Complex, 0);
643
644 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
645 } else
646 if (m_brush.GetStyle() == wxSTIPPLE)
647 {
648 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
649 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
650 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
651
652 XFillPolygon( (Display*) m_display, (Window) m_window,
653 (GC) m_brushGC, xpoints, n, Complex, 0);
654
655 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
656 }
657 else
658 {
659 XFillPolygon( (Display*) m_display, (Window) m_window,
660 (GC) m_brushGC, xpoints, n, Complex, 0);
661 }
662 }
663
664 if (m_pen.GetStyle () != wxTRANSPARENT)
665 {
666 // Close figure for XDrawLines
667 xpoints[i].x = xpoints[0].x;
668 xpoints[i].y = xpoints[0].y;
669
670 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n + 1, 0);
671 }
672 }
673
674 delete[] xpoints;
675 }
676
677 void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
678 {
679 wxCHECK_RET( Ok(), wxT("invalid window dc") );
680
681 wxCoord xx = XLOG2DEV(x);
682 wxCoord yy = YLOG2DEV(y);
683 wxCoord ww = m_signX * XLOG2DEVREL(width);
684 wxCoord hh = m_signY * YLOG2DEVREL(height);
685
686 // CMB: draw nothing if transformed w or h is 0
687 if (ww == 0 || hh == 0) return;
688
689 // CMB: handle -ve width and/or height
690 if (ww < 0) { ww = -ww; xx = xx - ww; }
691 if (hh < 0) { hh = -hh; yy = yy - hh; }
692
693 if (m_window)
694 {
695 if (m_brush.GetStyle() != wxTRANSPARENT)
696 {
697 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
698 {
699 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
700 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
701 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
702
703 XFillRectangle( (Display*) m_display, (Window) m_window,
704 (GC) m_textGC, xx, yy, ww, hh );
705
706 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
707 } else
708 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
709 {
710 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
711 m_deviceOriginX % 15, m_deviceOriginY % 15 );
712
713 XFillRectangle( (Display*) m_display, (Window) m_window,
714 (GC) m_brushGC, xx, yy, ww, hh );
715
716 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
717 } else
718 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
719 {
720 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
721 m_deviceOriginX % 16, m_deviceOriginY % 16 );
722
723 XFillRectangle( (Display*) m_display, (Window) m_window,
724 (GC) m_brushGC, xx, yy, ww, hh );
725
726 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
727 } else
728 if (m_brush.GetStyle() == wxSTIPPLE)
729 {
730 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
731 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
732 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
733
734 XFillRectangle( (Display*) m_display, (Window) m_window,
735 (GC) m_brushGC, xx, yy, ww, hh );
736
737 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
738 }
739 else
740 {
741 XFillRectangle( (Display*) m_display, (Window) m_window,
742 (GC) m_brushGC, xx, yy, ww, hh );
743 }
744 }
745
746 if (m_pen.GetStyle () != wxTRANSPARENT)
747 {
748 XDrawRectangle( (Display*) m_display, (Window) m_window,
749 (GC) m_penGC, xx, yy, ww-1, hh-1 );
750 }
751 }
752
753 CalcBoundingBox( x, y );
754 CalcBoundingBox( x + width, y + height );
755 }
756
757 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
758 {
759 // later
760 }
761
762 void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
763 {
764 wxCHECK_RET( Ok(), wxT("invalid window dc") );
765
766 wxCoord xx = XLOG2DEV(x);
767 wxCoord yy = YLOG2DEV(y);
768 wxCoord ww = m_signX * XLOG2DEVREL(width);
769 wxCoord hh = m_signY * YLOG2DEVREL(height);
770
771 // CMB: handle -ve width and/or height
772 if (ww < 0) { ww = -ww; xx = xx - ww; }
773 if (hh < 0) { hh = -hh; yy = yy - hh; }
774
775 if (m_window)
776 {
777 if (m_brush.GetStyle() != wxTRANSPARENT)
778 {
779 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
780 {
781 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
782 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
783 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
784
785 XFillArc( (Display*) m_display, (Window) m_window,
786 (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 );
787
788 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
789 } else
790 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
791 {
792 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
793 m_deviceOriginX % 15, m_deviceOriginY % 15 );
794
795 XFillArc( (Display*) m_display, (Window) m_window,
796 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
797
798 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
799 } else
800 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
801 {
802 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
803 m_deviceOriginX % 16, m_deviceOriginY % 16 );
804
805 XFillArc( (Display*) m_display, (Window) m_window,
806 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
807
808 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
809 } else
810 if (m_brush.GetStyle() == wxSTIPPLE)
811 {
812 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
813 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
814 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
815
816 XFillArc( (Display*) m_display, (Window) m_window,
817 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
818
819 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
820 }
821 else
822 {
823 XFillArc( (Display*) m_display, (Window) m_window,
824 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
825 }
826 }
827
828 if (m_pen.GetStyle () != wxTRANSPARENT)
829 {
830 XDrawArc( (Display*) m_display, (Window) m_window,
831 (GC) m_penGC, xx, yy, ww, hh, 0, 360*64 );
832 }
833 }
834
835 CalcBoundingBox( x, y );
836 CalcBoundingBox( x + width, y + height );
837 }
838
839 void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
840 {
841 DoDrawBitmap(icon, x, y, TRUE);
842 }
843
844 #if wxUSE_NANOX
845 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
846 wxCoord x, wxCoord y,
847 bool useMask )
848 {
849 wxCHECK_RET( Ok(), wxT("invalid window dc") );
850
851 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
852
853 bool is_mono = (bitmap.GetBitmap() != NULL);
854
855 /* scale/translate size and position */
856 int xx = XLOG2DEV(x);
857 int yy = YLOG2DEV(y);
858
859 int w = bitmap.GetWidth();
860 int h = bitmap.GetHeight();
861
862 CalcBoundingBox( x, y );
863 CalcBoundingBox( x + w, y + h );
864
865 if (!m_window) return;
866
867 int ww = XLOG2DEVREL(w);
868 int hh = YLOG2DEVREL(h);
869
870 /* compare to current clipping region */
871 if (!m_currentClippingRegion.IsNull())
872 {
873 wxRegion tmp( xx,yy,ww,hh );
874 tmp.Intersect( m_currentClippingRegion );
875 if (tmp.IsEmpty())
876 return;
877 }
878
879 /* scale bitmap if required */
880 wxBitmap use_bitmap;
881 if ((w != ww) || (h != hh))
882 {
883 wxImage image( bitmap );
884 image.Rescale( ww, hh );
885 #if 0
886 if (is_mono)
887 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
888 else
889 #endif
890 use_bitmap = image.ConvertToBitmap();
891 }
892 else
893 {
894 use_bitmap = bitmap;
895 }
896
897 /* apply mask if any */
898 WXPixmap mask = NULL;
899 if (use_bitmap.GetMask())
900 mask = use_bitmap.GetMask()->GetBitmap();
901
902 if (useMask && mask)
903 {
904 Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ;
905 Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ;
906 Pixmap bufPixmap = GrNewPixmap(w, h, 0);
907 GC gc = GrNewGC();
908 GrSetGCUseBackground(gc, FALSE);
909 GrSetGCMode(gc, GR_MODE_COPY);
910
911 // This code assumes that background and foreground
912 // colours are used in ROPs, like in MSW.
913 // Not sure if this is true.
914
915 // Copy destination to buffer.
916 // In DoBlit, we need this step because Blit has
917 // a ROP argument. Here, we don't need it.
918 // In DoBlit, we may be able to eliminate this step
919 // if we check if the rop = copy
920 #if 0
921 GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_window,
922 0, 0, GR_MODE_COPY);
923 #endif
924
925 // Copy src to buffer using selected raster op (none selected
926 // in DrawBitmap, so just use Gxcopy)
927 GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap,
928 0, 0, GR_MODE_COPY);
929
930 // Set masked area in buffer to BLACK (pixel value 0)
931 GrSetGCBackground(gc, WHITE);
932 GrSetGCForeground(gc, BLACK);
933 GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap,
934 0, 0, GR_MODE_AND);
935
936 // set unmasked area in dest to BLACK
937 GrSetGCBackground(gc, BLACK);
938 GrSetGCForeground(gc, WHITE);
939 GrCopyArea((Window) m_window, gc, xx, yy, w, h, maskPixmap,
940 0, 0, GR_MODE_AND);
941
942 // OR buffer to dest
943 GrCopyArea((Window) m_window, gc, xx, yy, w, h, bufPixmap,
944 0, 0, GR_MODE_OR);
945
946 GrDestroyGC(gc);
947 GrDestroyWindow(bufPixmap);
948 }
949 else
950 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
951 (GC) m_penGC, 0, 0, w, h, xx, yy );
952
953 /* remove mask again if any */
954 if (useMask && mask)
955 {
956 if (!m_currentClippingRegion.IsNull())
957 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
958 }
959 }
960
961 #else
962
963 // Normal X11
964 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
965 wxCoord x, wxCoord y,
966 bool useMask )
967 {
968 wxCHECK_RET( Ok(), wxT("invalid window dc") );
969
970 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
971
972 bool is_mono = (bitmap.GetBitmap() != NULL);
973
974 // scale/translate size and position
975 int xx = XLOG2DEV(x);
976 int yy = YLOG2DEV(y);
977
978 int w = bitmap.GetWidth();
979 int h = bitmap.GetHeight();
980
981 CalcBoundingBox( x, y );
982 CalcBoundingBox( x + w, y + h );
983
984 if (!m_window) return;
985
986 int ww = XLOG2DEVREL(w);
987 int hh = YLOG2DEVREL(h);
988
989 // compare to current clipping region
990 if (!m_currentClippingRegion.IsNull())
991 {
992 wxRegion tmp( xx,yy,ww,hh );
993 tmp.Intersect( m_currentClippingRegion );
994 if (tmp.IsEmpty())
995 return;
996 }
997
998 // scale bitmap if required
999 wxBitmap use_bitmap;
1000 if ((w != ww) || (h != hh))
1001 {
1002 wxImage image( bitmap );
1003 image.Rescale( ww, hh );
1004 #if 0
1005 if (is_mono)
1006 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1007 else
1008 #endif
1009 use_bitmap = image.ConvertToBitmap();
1010 }
1011 else
1012 {
1013 use_bitmap = bitmap;
1014 }
1015
1016 // apply mask if any
1017 WXPixmap mask = NULL;
1018 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1019
1020 if (useMask && mask)
1021 {
1022 WXPixmap new_mask = NULL;
1023 #if 0
1024 if (!m_currentClippingRegion.IsNull())
1025 {
1026 GdkColor col;
1027 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
1028 GdkGC *gc = gdk_gc_new( new_mask );
1029 col.pixel = 0;
1030 gdk_gc_set_foreground( gc, &col );
1031 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1032 col.pixel = 0;
1033 gdk_gc_set_background( gc, &col );
1034 col.pixel = 1;
1035 gdk_gc_set_foreground( gc, &col );
1036 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1037 gdk_gc_set_clip_origin( gc, -xx, -yy );
1038 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1039 gdk_gc_set_stipple( gc, mask );
1040 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1041 gdk_gc_unref( gc );
1042 }
1043 #endif
1044 if (is_mono)
1045 {
1046 if (new_mask)
1047 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1048 else
1049 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1050 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1051 }
1052 else
1053 {
1054 if (new_mask)
1055 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1056 else
1057 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1058 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1059 }
1060
1061 if (new_mask)
1062 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
1063 }
1064
1065 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1066 // drawing a mono-bitmap (XBitmap) we use the current text GC
1067 if (is_mono)
1068 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1069 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
1070 else
1071 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1072 (GC) m_penGC, 0, 0, w, h, xx, yy );
1073
1074 // remove mask again if any
1075 if (useMask && mask)
1076 {
1077 if (is_mono)
1078 {
1079 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1080 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1081 if (!m_currentClippingRegion.IsNull())
1082 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1083 }
1084 else
1085 {
1086 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1087 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1088 if (!m_currentClippingRegion.IsNull())
1089 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1090 }
1091 }
1092 }
1093 #endif
1094 // wxUSE_NANOX/!wxUSE_NANOX
1095
1096 bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
1097 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask,
1098 wxCoord xsrcMask, wxCoord ysrcMask )
1099 {
1100 /* this is the nth try to get this utterly useless function to
1101 work. it now completely ignores the scaling or translation
1102 of the source dc, but scales correctly on the target dc and
1103 knows about possible mask information in a memory dc. */
1104
1105 wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
1106
1107 wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
1108
1109 if (!m_window) return FALSE;
1110
1111 // transform the source DC coords to the device ones
1112 xsrc = source->XLOG2DEV(xsrc);
1113 ysrc = source->YLOG2DEV(ysrc);
1114
1115 wxClientDC *srcDC = (wxClientDC*)source;
1116 wxMemoryDC *memDC = (wxMemoryDC*)source;
1117
1118 bool use_bitmap_method = FALSE;
1119 bool is_mono = FALSE;
1120
1121 // TODO: use the mask origin when drawing transparently
1122 if (xsrcMask == -1 && ysrcMask == -1)
1123 {
1124 xsrcMask = xsrc;
1125 ysrcMask = ysrc;
1126 }
1127
1128 if (srcDC->m_isMemDC)
1129 {
1130 if (!memDC->m_selected.Ok()) return FALSE;
1131
1132 /* we use the "XCopyArea" way to copy a memory dc into
1133 y different window if the memory dc BOTH
1134 a) doesn't have any mask or its mask isn't used
1135 b) it is clipped
1136 c) is not 1-bit */
1137
1138 if (useMask && (memDC->m_selected.GetMask()))
1139 {
1140 /* we HAVE TO use the direct way for memory dcs
1141 that have mask since the XCopyArea doesn't know
1142 about masks */
1143 use_bitmap_method = TRUE;
1144 }
1145 else if (memDC->m_selected.GetDepth() == 1)
1146 {
1147 /* we HAVE TO use the direct way for memory dcs
1148 that are bitmaps because XCopyArea doesn't cope
1149 with different bit depths */
1150 is_mono = TRUE;
1151 use_bitmap_method = TRUE;
1152 }
1153 else if ((xsrc == 0) && (ysrc == 0) &&
1154 (width == memDC->m_selected.GetWidth()) &&
1155 (height == memDC->m_selected.GetHeight()))
1156 {
1157 /* we SHOULD use the direct way if all of the bitmap
1158 in the memory dc is copied in which case XCopyArea
1159 wouldn't be able able to boost performace by reducing
1160 the area to be scaled */
1161 use_bitmap_method = TRUE;
1162 }
1163 else
1164 {
1165 use_bitmap_method = FALSE;
1166 }
1167 }
1168
1169 CalcBoundingBox( xdest, ydest );
1170 CalcBoundingBox( xdest + width, ydest + height );
1171
1172 // scale/translate size and position
1173 wxCoord xx = XLOG2DEV(xdest);
1174 wxCoord yy = YLOG2DEV(ydest);
1175
1176 wxCoord ww = XLOG2DEVREL(width);
1177 wxCoord hh = YLOG2DEVREL(height);
1178
1179 // compare to current clipping region
1180 if (!m_currentClippingRegion.IsNull())
1181 {
1182 wxRegion tmp( xx,yy,ww,hh );
1183 tmp.Intersect( m_currentClippingRegion );
1184 if (tmp.IsEmpty())
1185 return TRUE;
1186 }
1187
1188 int old_logical_func = m_logicalFunction;
1189 SetLogicalFunction( logical_func );
1190
1191 if (use_bitmap_method)
1192 {
1193 // scale/translate bitmap size
1194 wxCoord bm_width = memDC->m_selected.GetWidth();
1195 wxCoord bm_height = memDC->m_selected.GetHeight();
1196
1197 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1198 wxCoord bm_hh = YLOG2DEVREL( bm_height );
1199
1200 // scale bitmap if required
1201 wxBitmap use_bitmap;
1202
1203 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1204 {
1205 wxImage image( memDC->m_selected );
1206 image = image.Scale( bm_ww, bm_hh );
1207
1208 #if 0
1209 if (is_mono)
1210 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1211 else
1212 #endif
1213 use_bitmap = image.ConvertToBitmap();
1214 }
1215 else
1216 {
1217 use_bitmap = memDC->m_selected;
1218 }
1219
1220 // apply mask if any
1221 WXPixmap mask = NULL;
1222 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1223
1224 if (useMask && mask)
1225 {
1226 WXPixmap new_mask = NULL;
1227 #if 0
1228 if (!m_currentClippingRegion.IsNull())
1229 {
1230 GdkColor col;
1231 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1232 GdkGC *gc = gdk_gc_new( new_mask );
1233 col.pixel = 0;
1234 gdk_gc_set_foreground( gc, &col );
1235 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1236 col.pixel = 0;
1237 gdk_gc_set_background( gc, &col );
1238 col.pixel = 1;
1239 gdk_gc_set_foreground( gc, &col );
1240 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1241 gdk_gc_set_clip_origin( gc, -xx, -yy );
1242 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1243 gdk_gc_set_stipple( gc, mask );
1244 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1245 gdk_gc_unref( gc );
1246 }
1247 #endif
1248 if (is_mono)
1249 {
1250 if (new_mask)
1251 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1252 else
1253 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1254 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1255 }
1256 else
1257 {
1258 if (new_mask)
1259 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1260 else
1261 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1262 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1263 }
1264
1265 if (new_mask)
1266 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
1267 }
1268
1269 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1270 // drawing a mono-bitmap (XBitmap) we use the current text GC
1271
1272 if (is_mono)
1273 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1274 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
1275 else
1276 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1277 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1278
1279 // remove mask again if any
1280 if (useMask && mask)
1281 {
1282 if (is_mono)
1283 {
1284 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1285 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1286 if (!m_currentClippingRegion.IsNull())
1287 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1288 }
1289 else
1290 {
1291 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1292 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1293 if (!m_currentClippingRegion.IsNull())
1294 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1295 }
1296 }
1297 }
1298 else // use_bitmap_method
1299 {
1300 if ((width != ww) || (height != hh))
1301 {
1302 /* Draw source window into a bitmap as we cannot scale
1303 a window in contrast to a bitmap. this would actually
1304 work with memory dcs as well, but we'd lose the mask
1305 information and waste one step in this process since
1306 a memory already has a bitmap. all this is slightly
1307 inefficient as we could take an XImage directly from
1308 an X window, but we'd then also have to care that
1309 the window is not outside the screen (in which case
1310 we'd get a BadMatch or what not).
1311 Is a double XGetImage and combined XGetPixel and
1312 XPutPixel really faster? I'm not sure. look at wxXt
1313 for a different implementation of the same problem. */
1314
1315 wxBitmap bitmap( width, height );
1316
1317 // copy including child window contents
1318 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1319 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
1320 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1321 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1322
1323 // scale image
1324 wxImage image( bitmap );
1325 image = image.Scale( ww, hh );
1326
1327 // convert to bitmap
1328 bitmap = image.ConvertToBitmap();
1329
1330 // draw scaled bitmap
1331 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window,
1332 (GC) m_penGC, 0, 0, width, height, xx, yy );
1333 }
1334 else
1335 {
1336 // No scaling and not a memory dc with a mask either
1337
1338 // copy including child window contents
1339 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1340 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window,
1341 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1342 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1343 }
1344 }
1345
1346 SetLogicalFunction( old_logical_func );
1347
1348 return TRUE;
1349 }
1350
1351 void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1352 {
1353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1354
1355 if (!m_window) return;
1356
1357 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1358
1359 wxCHECK_RET( xfont, wxT("invalid font") );
1360
1361 x = XLOG2DEV(x);
1362 y = YLOG2DEV(y);
1363
1364 #if 0
1365 wxCoord width = gdk_string_width( font, text.mbc_str() );
1366 wxCoord height = font->ascent + font->descent;
1367
1368 if ( m_backgroundMode == wxSOLID )
1369 {
1370 gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
1371 gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
1372 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
1373 }
1374 #endif
1375
1376 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
1377 #if !wxUSE_NANOX
1378 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
1379 #endif
1380 {
1381 XDrawString( (Display*) m_display, (Window) m_window,
1382 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1383 }
1384
1385 #if 0
1386 if (m_font.GetUnderlined())
1387 {
1388 wxCoord ul_y = y + XFontStructGetAscent(font);
1389 if (font->descent > 0) ul_y++;
1390 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
1391 }
1392
1393 width = wxCoord(width / m_scaleX);
1394 height = wxCoord(height / m_scaleY);
1395
1396 CalcBoundingBox (x + width, y + height);
1397 CalcBoundingBox (x, y);
1398 #endif
1399 }
1400
1401 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
1402 {
1403 // later
1404 }
1405
1406 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1407 wxCoord *descent, wxCoord *externalLeading,
1408 wxFont *font ) const
1409 {
1410 wxCHECK_RET( Ok(), "invalid dc" );
1411
1412 wxFont fontToUse = m_font;
1413 if (font) fontToUse = *font;
1414
1415 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
1416
1417 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
1418
1419 wxCHECK_RET( xfont, wxT("invalid font") );
1420
1421 int direction, ascent, descent2;
1422 XCharStruct overall;
1423
1424 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
1425 &ascent, &descent2, &overall);
1426
1427 if (width)
1428 *width = (wxCoord)( overall.width / m_scaleX );
1429 if (height)
1430 *height = (wxCoord)((ascent + descent2) / m_scaleY );
1431 if (descent)
1432 *descent = (wxCoord)(descent2 / m_scaleY );
1433 if (externalLeading)
1434 *externalLeading = 0; // ??
1435 }
1436
1437 wxCoord wxWindowDC::GetCharWidth() const
1438 {
1439 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1440
1441 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1442
1443 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1444
1445 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1446
1447 int direction, ascent, descent;
1448 XCharStruct overall;
1449
1450 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1451
1452 return (wxCoord)(overall.width / m_scaleX);
1453 }
1454
1455 wxCoord wxWindowDC::GetCharHeight() const
1456 {
1457 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1458
1459 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1460
1461 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1462
1463 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1464
1465 int direction, ascent, descent;
1466 XCharStruct overall;
1467
1468 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1469
1470 return (wxCoord)((ascent+descent) / m_scaleY);
1471 }
1472
1473 void wxWindowDC::Clear()
1474 {
1475 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1476
1477 if (!m_window) return;
1478
1479 /* - we either are a memory dc or have a window as the
1480 owner. anything else shouldn't happen.
1481 - we don't use gdk_window_clear() as we don't set
1482 the window's background colour anymore. it is too
1483 much pain to keep the DC's and the window's back-
1484 ground colour in synch. */
1485
1486 if (m_owner)
1487 {
1488 int width,height;
1489 m_owner->GetSize( &width, &height );
1490 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1491 return;
1492 }
1493
1494 if (m_isMemDC)
1495 {
1496 int width,height;
1497 GetSize( &width, &height );
1498 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1499 return;
1500 }
1501 }
1502
1503 void wxWindowDC::SetFont( const wxFont &font )
1504 {
1505 wxCHECK_RET( Ok(), "invalid dc" );
1506
1507 m_font = font;
1508 }
1509
1510 void wxWindowDC::SetPen( const wxPen &pen )
1511 {
1512 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1513
1514 if (m_pen == pen) return;
1515
1516 m_pen = pen;
1517
1518 if (!m_pen.Ok()) return;
1519
1520 if (!m_window) return;
1521
1522 int width = m_pen.GetWidth();
1523 if (width <= 0)
1524 {
1525 // CMB: if width is non-zero scale it with the dc
1526 width = 1;
1527 }
1528 else
1529 {
1530 // X doesn't allow different width in x and y and so we take
1531 // the average
1532 double w = 0.5 +
1533 ( fabs((double) XLOG2DEVREL(width)) +
1534 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1535 width = (int)w;
1536 }
1537
1538 static const wxX11Dash dotted[] = {1, 1};
1539 static const wxX11Dash short_dashed[] = {2, 2};
1540 static const wxX11Dash long_dashed[] = {2, 4};
1541 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1542
1543 // We express dash pattern in pen width unit, so we are
1544 // independent of zoom factor and so on...
1545 int req_nb_dash;
1546 const wxX11Dash *req_dash;
1547
1548 int lineStyle = LineSolid;
1549 switch (m_pen.GetStyle())
1550 {
1551 case wxUSER_DASH:
1552 {
1553 lineStyle = LineOnOffDash;
1554 req_nb_dash = m_pen.GetDashCount();
1555 req_dash = (wxX11Dash*)m_pen.GetDash();
1556 break;
1557 }
1558 case wxDOT:
1559 {
1560 lineStyle = LineOnOffDash;
1561 req_nb_dash = 2;
1562 req_dash = dotted;
1563 break;
1564 }
1565 case wxLONG_DASH:
1566 {
1567 lineStyle = LineOnOffDash;
1568 req_nb_dash = 2;
1569 req_dash = long_dashed;
1570 break;
1571 }
1572 case wxSHORT_DASH:
1573 {
1574 lineStyle = LineOnOffDash;
1575 req_nb_dash = 2;
1576 req_dash = short_dashed;
1577 break;
1578 }
1579 case wxDOT_DASH:
1580 {
1581 // lineStyle = LineDoubleDash;
1582 lineStyle = LineOnOffDash;
1583 req_nb_dash = 4;
1584 req_dash = dotted_dashed;
1585 break;
1586 }
1587
1588 case wxTRANSPARENT:
1589 case wxSTIPPLE_MASK_OPAQUE:
1590 case wxSTIPPLE:
1591 case wxSOLID:
1592 default:
1593 {
1594 lineStyle = LineSolid;
1595 req_dash = (wxX11Dash*)NULL;
1596 req_nb_dash = 0;
1597 break;
1598 }
1599 }
1600
1601 int capStyle = CapRound;
1602 switch (m_pen.GetCap())
1603 {
1604 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1605 case wxCAP_BUTT: { capStyle = CapButt; break; }
1606 case wxCAP_ROUND:
1607 default:
1608 {
1609 if (width <= 1)
1610 {
1611 width = 0;
1612 capStyle = CapNotLast;
1613 }
1614 else
1615 {
1616 capStyle = CapRound;
1617 }
1618 break;
1619 }
1620 }
1621
1622 int joinStyle = JoinRound;
1623 switch (m_pen.GetJoin())
1624 {
1625 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1626 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
1627 case wxJOIN_ROUND:
1628 default: { joinStyle = JoinRound; break; }
1629 }
1630
1631 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
1632
1633 m_pen.GetColour().CalcPixel( m_cmap );
1634 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1635 }
1636
1637 void wxWindowDC::SetBrush( const wxBrush &brush )
1638 {
1639 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1640
1641 if (m_brush == brush) return;
1642
1643 m_brush = brush;
1644
1645 if (!m_brush.Ok()) return;
1646
1647 if (!m_window) return;
1648
1649 m_brush.GetColour().CalcPixel( m_cmap );
1650 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1651
1652 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1653
1654 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
1655 {
1656 if (m_brush.GetStipple()->GetPixmap())
1657 {
1658 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1659 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
1660 }
1661 else
1662 {
1663 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1664 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1665 }
1666 }
1667
1668 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1669 {
1670 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
1671 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1672 }
1673
1674 if (IS_HATCH(m_brush.GetStyle()))
1675 {
1676 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1677 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1678 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1679 }
1680 }
1681
1682 void wxWindowDC::SetBackground( const wxBrush &brush )
1683 {
1684 /* CMB 21/7/98: Added SetBackground. Sets background brush
1685 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1686
1687 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1688
1689 if (m_backgroundBrush == brush) return;
1690
1691 m_backgroundBrush = brush;
1692
1693 if (!m_backgroundBrush.Ok()) return;
1694
1695 if (!m_window) return;
1696
1697 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1698 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1699 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1700 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1701 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1702
1703 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
1704
1705 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
1706 {
1707 if (m_backgroundBrush.GetStipple()->GetPixmap())
1708 {
1709 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1710 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
1711 }
1712 else
1713 {
1714 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1715 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
1716 }
1717 }
1718
1719 if (IS_HATCH(m_backgroundBrush.GetStyle()))
1720 {
1721 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1722 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1723 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
1724 }
1725 }
1726
1727 void wxWindowDC::SetLogicalFunction( int function )
1728 {
1729 wxCHECK_RET( Ok(), "invalid dc" );
1730
1731 int x_function;
1732
1733 if (m_logicalFunction == function)
1734 return;
1735
1736 // VZ: shouldn't this be a CHECK?
1737 if (!m_window)
1738 return;
1739
1740 switch (function)
1741 {
1742 case wxCLEAR:
1743 x_function = GXclear;
1744 break;
1745 case wxXOR:
1746 x_function = GXxor;
1747 break;
1748 case wxINVERT:
1749 x_function = GXinvert;
1750 break;
1751 case wxOR_REVERSE:
1752 x_function = GXorReverse;
1753 break;
1754 case wxAND_REVERSE:
1755 x_function = GXandReverse;
1756 break;
1757 case wxAND:
1758 x_function = GXand;
1759 break;
1760 case wxOR:
1761 x_function = GXor;
1762 break;
1763 case wxAND_INVERT:
1764 x_function = GXandInverted;
1765 break;
1766 case wxNO_OP:
1767 x_function = GXnoop;
1768 break;
1769 case wxNOR:
1770 x_function = GXnor;
1771 break;
1772 case wxEQUIV:
1773 x_function = GXequiv;
1774 break;
1775 case wxSRC_INVERT:
1776 x_function = GXcopyInverted;
1777 break;
1778 case wxOR_INVERT:
1779 x_function = GXorInverted;
1780 break;
1781 case wxNAND:
1782 x_function = GXnand;
1783 break;
1784 case wxSET:
1785 x_function = GXset;
1786 break;
1787 case wxCOPY:
1788 default:
1789 x_function = GXcopy;
1790 break;
1791 }
1792
1793 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
1794 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
1795
1796 // to stay compatible with wxMSW, we don't apply ROPs to the text
1797 // operations (i.e. DrawText/DrawRotatedText).
1798 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1799 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
1800
1801 m_logicalFunction = function;
1802 }
1803
1804 void wxWindowDC::SetTextForeground( const wxColour &col )
1805 {
1806 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1807
1808 // don't set m_textForegroundColour to an invalid colour as we'd crash
1809 // later then (we use m_textForegroundColour.GetColor() without checking
1810 // in a few places)
1811 if ( !col.Ok() || (m_textForegroundColour == col) )
1812 return;
1813
1814 m_textForegroundColour = col;
1815
1816 if (m_window)
1817 {
1818 m_textForegroundColour.CalcPixel( m_cmap );
1819 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
1820 }
1821 }
1822
1823 void wxWindowDC::SetTextBackground( const wxColour &col )
1824 {
1825 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1826
1827 // same as above
1828 if ( !col.Ok() || (m_textBackgroundColour == col) )
1829 return;
1830
1831 m_textBackgroundColour = col;
1832
1833 if (m_window)
1834 {
1835 m_textBackgroundColour.CalcPixel( m_cmap );
1836 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
1837 }
1838 }
1839
1840 void wxWindowDC::SetBackgroundMode( int mode )
1841 {
1842 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1843
1844 m_backgroundMode = mode;
1845
1846 #if wxUSE_NANOX
1847 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
1848 #endif
1849
1850 if (!m_window) return;
1851
1852 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1853 // transparent/solid background mode
1854
1855 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1856 {
1857 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
1858 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
1859 }
1860 }
1861
1862 void wxWindowDC::SetPalette( const wxPalette& palette )
1863 {
1864 #if 0
1865 if (m_window)
1866 {
1867 if (palette.Ok())
1868 /* Use GetXColormap */
1869 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1870 (Colormap) palette.GetXColormap());
1871 else
1872 /* Use wxGetMainColormap */
1873 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1874 (Colormap) wxTheApp->GetMainColormap(m_display));
1875 }
1876 #endif
1877 }
1878
1879 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
1880 {
1881 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1882
1883 if (!m_window) return;
1884
1885 wxRect rect;
1886 rect.x = XLOG2DEV(x);
1887 rect.y = YLOG2DEV(y);
1888 rect.width = XLOG2DEVREL(width);
1889 rect.height = YLOG2DEVREL(height);
1890
1891 if (!m_currentClippingRegion.IsNull())
1892 m_currentClippingRegion.Intersect( rect );
1893 else
1894 m_currentClippingRegion.Union( rect );
1895
1896 #if USE_PAINT_REGION
1897 if (!m_paintClippingRegion.IsNull())
1898 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1899 #endif
1900
1901 wxCoord xx, yy, ww, hh;
1902 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1903 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1904
1905 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1906 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1907 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1908 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1909 }
1910
1911 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1912 {
1913 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1914
1915 if (region.Empty())
1916 {
1917 DestroyClippingRegion();
1918 return;
1919 }
1920
1921 if (!m_window) return;
1922
1923 if (!m_currentClippingRegion.IsNull())
1924 m_currentClippingRegion.Intersect( region );
1925 else
1926 m_currentClippingRegion.Union( region );
1927
1928 #if USE_PAINT_REGION
1929 if (!m_paintClippingRegion.IsNull())
1930 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1931 #endif
1932
1933 wxCoord xx, yy, ww, hh;
1934 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1935 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1936
1937 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1938 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1939 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1940 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1941 }
1942
1943 void wxWindowDC::DestroyClippingRegion()
1944 {
1945 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1946
1947 wxDC::DestroyClippingRegion();
1948
1949 m_currentClippingRegion.Clear();
1950
1951 #if USE_PAINT_REGION
1952 if (!m_paintClippingRegion.IsEmpty())
1953 m_currentClippingRegion.Union( m_paintClippingRegion );
1954 #endif
1955
1956 if (!m_window) return;
1957
1958 if (m_currentClippingRegion.IsEmpty())
1959 {
1960 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1961 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
1962 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1963 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
1964 }
1965 else
1966 {
1967 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1968 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1969 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1970 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1971 }
1972 }
1973
1974 void wxWindowDC::Destroy()
1975 {
1976 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
1977 m_penGC = NULL;
1978 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
1979 m_brushGC = NULL;
1980 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
1981 m_textGC = NULL;
1982 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
1983 m_bgGC = NULL;
1984 }
1985
1986 void wxWindowDC::ComputeScaleAndOrigin()
1987 {
1988 /* CMB: copy scale to see if it changes */
1989 double origScaleX = m_scaleX;
1990 double origScaleY = m_scaleY;
1991
1992 wxDC::ComputeScaleAndOrigin();
1993
1994 /* CMB: if scale has changed call SetPen to recalulate the line width */
1995 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
1996 (m_pen.Ok()))
1997 {
1998 /* this is a bit artificial, but we need to force wxDC to think
1999 the pen has changed */
2000 wxPen pen = m_pen;
2001 m_pen = wxNullPen;
2002 SetPen( pen );
2003 }
2004 }
2005
2006 wxSize wxWindowDC::GetPPI() const
2007 {
2008 return wxSize(100, 100);
2009 }
2010
2011 int wxWindowDC::GetDepth() const
2012 {
2013 wxFAIL_MSG(wxT("not implemented"));
2014
2015 return -1;
2016 }
2017
2018 // ----------------------------------------------------------------------------
2019 // wxPaintDC
2020 // ----------------------------------------------------------------------------
2021
2022 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2023
2024 wxPaintDC::wxPaintDC(wxWindow* win)
2025 : wxClientDC(win)
2026 {
2027 #if USE_PAINT_REGION
2028 if (!win->GetClipPaintRegion())
2029 return;
2030
2031 m_paintClippingRegion = win->GetUpdateRegion();
2032 Region region = (Region) m_paintClippingRegion.GetX11Region();
2033 if (region)
2034 {
2035 m_paintClippingRegion = win->GetUpdateRegion();
2036 Region region2 = (Region) m_paintClippingRegion.GetX11Region();
2037 if (region2)
2038 {
2039 m_currentClippingRegion.Union( m_paintClippingRegion );
2040
2041 XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
2042 XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
2043 XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
2044 XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
2045 }
2046 }
2047 #endif // USE_PAINT_REGION
2048 }
2049
2050 //-----------------------------------------------------------------------------
2051 // wxClientDC
2052 //-----------------------------------------------------------------------------
2053
2054 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2055
2056 wxClientDC::wxClientDC( wxWindow *win )
2057 : wxWindowDC( win )
2058 {
2059 wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
2060
2061 #ifdef __WXUNIVERSAL__
2062 wxPoint ptOrigin = win->GetClientAreaOrigin();
2063 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2064 wxSize size = win->GetClientSize();
2065 SetClippingRegion(wxPoint(0, 0), size);
2066 #endif // __WXUNIVERSAL__
2067 }
2068
2069 void wxClientDC::DoGetSize(int *width, int *height) const
2070 {
2071 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2072
2073 m_owner->GetClientSize( width, height );
2074 }
2075
2076 // ----------------------------------------------------------------------------
2077 // wxDCModule
2078 // ----------------------------------------------------------------------------
2079
2080 class wxDCModule : public wxModule
2081 {
2082 public:
2083 bool OnInit();
2084 void OnExit();
2085
2086 private:
2087 DECLARE_DYNAMIC_CLASS(wxDCModule)
2088 };
2089
2090 IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
2091
2092 bool wxDCModule::OnInit()
2093 {
2094 wxInitGCPool();
2095 return TRUE;
2096 }
2097
2098 void wxDCModule::OnExit()
2099 {
2100 wxCleanUpGCPool();
2101 }