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