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