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