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