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