]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dcclient.cpp
fixed (rare but fatal) bug in wxWindowDisabler
[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;
f3d05fe4 1455#if GTK_CHECK_VERSION(1,2,7)
3fa056ab
JJ
1456 gdk_gc_set_dashes( m_penGC, 0, (gint8*) real_req_dash,
1457 req_nb_dash );
f3d05fe4
VS
1458#else
1459 gdk_gc_set_dashes( m_penGC, 0, real_req_dash,
1460 req_nb_dash );
1461#endif
112c5086
RR
1462 delete[] real_req_dash;
1463 }
1464 else
1465 {
1466 // No Memory. We use non-scaled dash pattern...
f3d05fe4 1467#if GTK_CHECK_VERSION(1,2,7)
3fa056ab 1468 gdk_gc_set_dashes( m_penGC, 0, (gint8*)req_dash, req_nb_dash );
f3d05fe4
VS
1469#else
1470 gdk_gc_set_dashes( m_penGC, 0, (char*)req_dash, req_nb_dash );
1471#endif
112c5086
RR
1472 }
1473 }
953704c1 1474#endif
7d5af6fa 1475
265898fd
RR
1476 GdkCapStyle capStyle = GDK_CAP_ROUND;
1477 switch (m_pen.GetCap())
1478 {
265898fd
RR
1479 case wxCAP_PROJECTING: { capStyle = GDK_CAP_PROJECTING; break; }
1480 case wxCAP_BUTT: { capStyle = GDK_CAP_BUTT; break; }
d4aa3a4b
RR
1481 case wxCAP_ROUND:
1482 default:
72174350 1483 {
d4aa3a4b
RR
1484 if (width <= 1)
1485 {
1486 width = 0;
1487 capStyle = GDK_CAP_NOT_LAST;
1488 }
1489 else
1490 {
1491 capStyle = GDK_CAP_ROUND;
1492 }
72174350 1493 break;
d4aa3a4b 1494 }
265898fd 1495 }
7d5af6fa 1496
265898fd
RR
1497 GdkJoinStyle joinStyle = GDK_JOIN_ROUND;
1498 switch (m_pen.GetJoin())
1499 {
1500 case wxJOIN_BEVEL: { joinStyle = GDK_JOIN_BEVEL; break; }
265898fd 1501 case wxJOIN_MITER: { joinStyle = GDK_JOIN_MITER; break; }
d4aa3a4b
RR
1502 case wxJOIN_ROUND:
1503 default: { joinStyle = GDK_JOIN_ROUND; break; }
265898fd 1504 }
7d5af6fa 1505
265898fd 1506 gdk_gc_set_line_attributes( m_penGC, width, lineStyle, capStyle, joinStyle );
7d5af6fa 1507
265898fd
RR
1508 m_pen.GetColour().CalcPixel( m_cmap );
1509 gdk_gc_set_foreground( m_penGC, m_pen.GetColour().GetColor() );
903f689b 1510}
c801d85f 1511
ec758a20 1512void wxWindowDC::SetBrush( const wxBrush &brush )
c801d85f 1513{
223d09f6 1514 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1515
265898fd 1516 if (m_brush == brush) return;
7d5af6fa 1517
265898fd 1518 m_brush = brush;
7d5af6fa 1519
265898fd 1520 if (!m_brush.Ok()) return;
7d5af6fa 1521
6db90681 1522 if (!m_window) return;
7d5af6fa 1523
265898fd
RR
1524 m_brush.GetColour().CalcPixel( m_cmap );
1525 gdk_gc_set_foreground( m_brushGC, m_brush.GetColour().GetColor() );
7d5af6fa 1526
956dbab1 1527 gdk_gc_set_fill( m_brushGC, GDK_SOLID );
7d5af6fa 1528
4fcd73bd 1529 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
265898fd 1530 {
4fcd73bd 1531 if (m_brush.GetStipple()->GetPixmap())
7d5af6fa 1532 {
956dbab1 1533 gdk_gc_set_fill( m_brushGC, GDK_TILED );
cd25b18c 1534 gdk_gc_set_tile( m_brushGC, m_brush.GetStipple()->GetPixmap() );
7d5af6fa 1535 }
b0e0d661 1536 else
7d5af6fa 1537 {
956dbab1 1538 gdk_gc_set_fill( m_brushGC, GDK_STIPPLED );
4fcd73bd 1539 gdk_gc_set_stipple( m_brushGC, m_brush.GetStipple()->GetBitmap() );
7d5af6fa 1540 }
265898fd 1541 }
7d5af6fa 1542
de2d2cdc
VZ
1543 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1544 {
e1208c31
RR
1545 gdk_gc_set_fill( m_textGC, GDK_OPAQUE_STIPPLED);
1546 gdk_gc_set_stipple( m_textGC, m_brush.GetStipple()->GetMask()->GetBitmap() );
de2d2cdc
VZ
1547 }
1548
265898fd
RR
1549 if (IS_HATCH(m_brush.GetStyle()))
1550 {
956dbab1 1551 gdk_gc_set_fill( m_brushGC, GDK_STIPPLED );
265898fd
RR
1552 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1553 gdk_gc_set_stipple( m_brushGC, hatches[num] );
1554 }
903f689b 1555}
c801d85f 1556
ec758a20 1557void wxWindowDC::SetBackground( const wxBrush &brush )
46dc76ba 1558{
bbbbe360
RR
1559 /* CMB 21/7/98: Added SetBackground. Sets background brush
1560 * for Clear() and bg colour for shapes filled with cross-hatch brush */
7d5af6fa 1561
223d09f6 1562 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1563
265898fd 1564 if (m_backgroundBrush == brush) return;
7d5af6fa 1565
265898fd 1566 m_backgroundBrush = brush;
7d5af6fa 1567
265898fd 1568 if (!m_backgroundBrush.Ok()) return;
7d5af6fa 1569
6db90681 1570 if (!m_window) return;
7d5af6fa 1571
265898fd
RR
1572 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1573 gdk_gc_set_background( m_brushGC, m_backgroundBrush.GetColour().GetColor() );
a802c3a1 1574 gdk_gc_set_background( m_penGC, m_backgroundBrush.GetColour().GetColor() );
031b2a7b 1575 gdk_gc_set_background( m_bgGC, m_backgroundBrush.GetColour().GetColor() );
265898fd 1576 gdk_gc_set_foreground( m_bgGC, m_backgroundBrush.GetColour().GetColor() );
3417c2cd
RR
1577
1578 gdk_gc_set_fill( m_bgGC, GDK_SOLID );
7d5af6fa 1579
cd25b18c 1580 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
265898fd 1581 {
fd128b0c 1582 if (m_backgroundBrush.GetStipple()->GetPixmap())
7d5af6fa 1583 {
3417c2cd 1584 gdk_gc_set_fill( m_bgGC, GDK_TILED );
fd128b0c 1585 gdk_gc_set_tile( m_bgGC, m_backgroundBrush.GetStipple()->GetPixmap() );
7d5af6fa 1586 }
cd25b18c 1587 else
7d5af6fa 1588 {
3417c2cd 1589 gdk_gc_set_fill( m_bgGC, GDK_STIPPLED );
fd128b0c 1590 gdk_gc_set_stipple( m_bgGC, m_backgroundBrush.GetStipple()->GetBitmap() );
7d5af6fa 1591 }
265898fd 1592 }
7d5af6fa 1593
265898fd
RR
1594 if (IS_HATCH(m_backgroundBrush.GetStyle()))
1595 {
3417c2cd 1596 gdk_gc_set_fill( m_bgGC, GDK_STIPPLED );
265898fd
RR
1597 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1598 gdk_gc_set_stipple( m_bgGC, hatches[num] );
bbbbe360 1599 }
903f689b 1600}
46dc76ba 1601
ec758a20 1602void wxWindowDC::SetLogicalFunction( int function )
c801d85f 1603{
223d09f6 1604 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1605
72174350
VZ
1606 if (m_logicalFunction == function)
1607 return;
1608
1609 // VZ: shouldn't this be a CHECK?
1610 if (!m_window)
1611 return;
01eaf507 1612
265898fd
RR
1613 GdkFunction mode = GDK_COPY;
1614 switch (function)
1615 {
3c679789
RR
1616 case wxXOR: mode = GDK_XOR; break;
1617 case wxINVERT: mode = GDK_INVERT; break;
01eaf507 1618#if (GTK_MINOR_VERSION > 0)
3c679789
RR
1619 case wxOR_REVERSE: mode = GDK_OR_REVERSE; break;
1620 case wxAND_REVERSE: mode = GDK_AND_REVERSE; break;
1621 case wxCLEAR: mode = GDK_CLEAR; break;
1622 case wxSET: mode = GDK_SET; break;
1623 case wxOR_INVERT: mode = GDK_OR_INVERT; break;
1624 case wxAND: mode = GDK_AND; break;
1625 case wxOR: mode = GDK_OR; break;
1626 case wxEQUIV: mode = GDK_EQUIV; break;
1627 case wxNAND: mode = GDK_NAND; break;
1628 case wxAND_INVERT: mode = GDK_AND_INVERT; break;
7d5af6fa
VZ
1629 case wxCOPY: mode = GDK_COPY; break;
1630 case wxNO_OP: mode = GDK_NOOP; break;
1631 case wxSRC_INVERT: mode = GDK_COPY_INVERT; break;
72174350 1632
2d52841d
RR
1633 // unsupported by GTK
1634 case wxNOR: mode = GDK_COPY; break;
c96faa7c 1635#endif
01eaf507 1636 default:
7d5af6fa 1637 {
223d09f6 1638 wxFAIL_MSG( wxT("unsupported logical function") );
7d5af6fa
VZ
1639 break;
1640 }
265898fd 1641 }
7d5af6fa 1642
265898fd 1643 m_logicalFunction = function;
7d5af6fa 1644
265898fd
RR
1645 gdk_gc_set_function( m_penGC, mode );
1646 gdk_gc_set_function( m_brushGC, mode );
72174350
VZ
1647
1648 // to stay compatible with wxMSW, we don't apply ROPs to the text
3d2d8da1
RR
1649 // operations (i.e. DrawText/DrawRotatedText).
1650 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1651 gdk_gc_set_function( m_textGC, mode );
903f689b 1652}
c801d85f 1653
ec758a20 1654void wxWindowDC::SetTextForeground( const wxColour &col )
c801d85f 1655{
223d09f6 1656 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1657
265898fd 1658 if (m_textForegroundColour == col) return;
7d5af6fa 1659
265898fd
RR
1660 m_textForegroundColour = col;
1661 if (!m_textForegroundColour.Ok()) return;
7d5af6fa 1662
6db90681 1663 if (!m_window) return;
7d5af6fa 1664
265898fd
RR
1665 m_textForegroundColour.CalcPixel( m_cmap );
1666 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
903f689b 1667}
c801d85f 1668
ec758a20 1669void wxWindowDC::SetTextBackground( const wxColour &col )
c801d85f 1670{
223d09f6 1671 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1672
265898fd 1673 if (m_textBackgroundColour == col) return;
7d5af6fa 1674
265898fd
RR
1675 m_textBackgroundColour = col;
1676 if (!m_textBackgroundColour.Ok()) return;
7d5af6fa 1677
6db90681 1678 if (!m_window) return;
7d5af6fa 1679
265898fd
RR
1680 m_textBackgroundColour.CalcPixel( m_cmap );
1681 gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() );
903f689b 1682}
c801d85f 1683
ec758a20 1684void wxWindowDC::SetBackgroundMode( int mode )
c801d85f 1685{
223d09f6 1686 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1687
265898fd 1688 m_backgroundMode = mode;
46dc76ba 1689
6db90681 1690 if (!m_window) return;
7d5af6fa 1691
265898fd
RR
1692 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1693 // transparent/solid background mode
7d5af6fa 1694
265898fd
RR
1695 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1696 {
1697 gdk_gc_set_fill( m_brushGC,
1698 (m_backgroundMode == wxTRANSPARENT) ? GDK_STIPPLED : GDK_OPAQUE_STIPPLED);
1699 }
903f689b 1700}
c801d85f 1701
ec758a20 1702void wxWindowDC::SetPalette( const wxPalette& WXUNUSED(palette) )
c801d85f 1703{
223d09f6 1704 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
903f689b 1705}
c801d85f 1706
72cdf4c9 1707void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 1708{
223d09f6 1709 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1710
6db90681 1711 if (!m_window) return;
7d5af6fa 1712
3d2d8da1 1713 wxRect rect;
265898fd
RR
1714 rect.x = XLOG2DEV(x);
1715 rect.y = YLOG2DEV(y);
1716 rect.width = XLOG2DEVREL(width);
1717 rect.height = YLOG2DEVREL(height);
3d2d8da1 1718
e1208c31 1719 if (!m_currentClippingRegion.IsNull())
993f97ee
RR
1720 m_currentClippingRegion.Intersect( rect );
1721 else
1722 m_currentClippingRegion.Union( rect );
1723
809934d2 1724#if USE_PAINT_REGION
e1208c31 1725 if (!m_paintClippingRegion.IsNull())
3d2d8da1 1726 m_currentClippingRegion.Intersect( m_paintClippingRegion );
809934d2 1727#endif
3d2d8da1 1728
ee8dbe63
RL
1729 wxCoord xx, yy, ww, hh;
1730 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1731 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1732
3d2d8da1
RR
1733 gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
1734 gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() );
1735 gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
1736 gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() );
903f689b 1737}
c801d85f 1738
b0e0d661 1739void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion &region )
463c1fa1 1740{
223d09f6 1741 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1742
463c1fa1
RR
1743 if (region.Empty())
1744 {
1745 DestroyClippingRegion();
1746 return;
1747 }
7d5af6fa 1748
6db90681 1749 if (!m_window) return;
3d2d8da1 1750
e1208c31 1751 if (!m_currentClippingRegion.IsNull())
993f97ee
RR
1752 m_currentClippingRegion.Intersect( region );
1753 else
1754 m_currentClippingRegion.Union( region );
1755
809934d2 1756#if USE_PAINT_REGION
e1208c31 1757 if (!m_paintClippingRegion.IsNull())
3d2d8da1 1758 m_currentClippingRegion.Intersect( m_paintClippingRegion );
809934d2 1759#endif
3d2d8da1 1760
ee8dbe63
RL
1761 wxCoord xx, yy, ww, hh;
1762 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1763 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1764
3d2d8da1
RR
1765 gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
1766 gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() );
1767 gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
1768 gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() );
463c1fa1
RR
1769}
1770
4bc67cc5 1771void wxWindowDC::DestroyClippingRegion()
c801d85f 1772{
223d09f6 1773 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1774
265898fd 1775 wxDC::DestroyClippingRegion();
7d5af6fa 1776
3d2d8da1
RR
1777 m_currentClippingRegion.Clear();
1778
993f97ee 1779#if USE_PAINT_REGION
3d2d8da1
RR
1780 if (!m_paintClippingRegion.IsEmpty())
1781 m_currentClippingRegion.Union( m_paintClippingRegion );
993f97ee 1782#endif
3d2d8da1 1783
6db90681 1784 if (!m_window) return;
7d5af6fa 1785
3d2d8da1
RR
1786 if (m_currentClippingRegion.IsEmpty())
1787 {
1788 gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL );
1789 gdk_gc_set_clip_rectangle( m_brushGC, (GdkRectangle *) NULL );
1790 gdk_gc_set_clip_rectangle( m_textGC, (GdkRectangle *) NULL );
1791 gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL );
1792 }
1793 else
1794 {
1795 gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
1796 gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() );
1797 gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
1798 gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() );
1799 }
903f689b 1800}
c801d85f 1801
4bc67cc5 1802void wxWindowDC::Destroy()
dbf858b5 1803{
3d2d8da1 1804 if (m_penGC) wxFreePoolGC( m_penGC );
265898fd 1805 m_penGC = (GdkGC*) NULL;
3d2d8da1 1806 if (m_brushGC) wxFreePoolGC( m_brushGC );
265898fd 1807 m_brushGC = (GdkGC*) NULL;
3d2d8da1 1808 if (m_textGC) wxFreePoolGC( m_textGC );
265898fd 1809 m_textGC = (GdkGC*) NULL;
3d2d8da1 1810 if (m_bgGC) wxFreePoolGC( m_bgGC );
265898fd 1811 m_bgGC = (GdkGC*) NULL;
dbf858b5
RR
1812}
1813
238d735d
RR
1814void wxWindowDC::ComputeScaleAndOrigin()
1815{
1816 /* CMB: copy scale to see if it changes */
1817 double origScaleX = m_scaleX;
1818 double origScaleY = m_scaleY;
1819
1820 wxDC::ComputeScaleAndOrigin();
1821
1822 /* CMB: if scale has changed call SetPen to recalulate the line width */
1823 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
1824 (m_pen.Ok()))
1825 {
1826 /* this is a bit artificial, but we need to force wxDC to think
1827 the pen has changed */
1828 wxPen pen = m_pen;
1829 m_pen = wxNullPen;
1830 SetPen( pen );
1831 }
1832}
1833
b0e0d661
VZ
1834// Resolution in pixels per logical inch
1835wxSize wxWindowDC::GetPPI() const
1836{
1837 return wxSize(100, 100);
1838}
1839
1840int wxWindowDC::GetDepth() const
c801d85f 1841{
223d09f6 1842 wxFAIL_MSG(wxT("not implemented"));
b0e0d661
VZ
1843
1844 return -1;
903f689b 1845}
c801d85f 1846
d54e4256 1847#if wxUSE_SPLINES
c801d85f
KB
1848// ----------------------------------- spline code ----------------------------------------
1849
1850void wx_quadratic_spline(double a1, double b1, double a2, double b2,
1851 double a3, double b3, double a4, double b4);
4bc67cc5 1852void wx_clear_stack();
c801d85f
KB
1853int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
1854 double *y3, double *x4, double *y4);
1855void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
1856 double x4, double y4);
1857static bool wx_spline_add_point(double x, double y);
1858static void wx_spline_draw_point_array(wxDC *dc);
1859
1860wxList wx_spline_point_list;
1861
b0e0d661
VZ
1862#define half(z1, z2) ((z1+z2)/2.0)
1863#define THRESHOLD 5
c801d85f
KB
1864
1865/* iterative version */
1866
1867void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
1868 double b4)
1869{
1870 register double xmid, ymid;
1871 double x1, y1, x2, y2, x3, y3, x4, y4;
1872
1873 wx_clear_stack();
1874 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
1875
1876 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
1877 xmid = (double)half(x2, x3);
1878 ymid = (double)half(y2, y3);
b0e0d661
VZ
1879 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
1880 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
c801d85f
KB
1881 wx_spline_add_point( x1, y1 );
1882 wx_spline_add_point( xmid, ymid );
b0e0d661 1883 } else {
c801d85f
KB
1884 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
1885 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
1886 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
1887 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
b0e0d661 1888 }
c801d85f
KB
1889 }
1890}
1891
1892/* utilities used by spline drawing routines */
1893
1894typedef struct wx_spline_stack_struct {
1895 double x1, y1, x2, y2, x3, y3, x4, y4;
1896} Stack;
1897
1898#define SPLINE_STACK_DEPTH 20
1899static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
1900static Stack *wx_stack_top;
1901static int wx_stack_count;
1902
4bc67cc5 1903void wx_clear_stack()
c801d85f
KB
1904{
1905 wx_stack_top = wx_spline_stack;
1906 wx_stack_count = 0;
1907}
1908
1909void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
1910{
1911 wx_stack_top->x1 = x1;
1912 wx_stack_top->y1 = y1;
1913 wx_stack_top->x2 = x2;
1914 wx_stack_top->y2 = y2;
1915 wx_stack_top->x3 = x3;
1916 wx_stack_top->y3 = y3;
1917 wx_stack_top->x4 = x4;
1918 wx_stack_top->y4 = y4;
1919 wx_stack_top++;
1920 wx_stack_count++;
1921}
1922
1923int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
1924 double *x3, double *y3, double *x4, double *y4)
1925{
1926 if (wx_stack_count == 0)
b0e0d661 1927 return (0);
c801d85f
KB
1928 wx_stack_top--;
1929 wx_stack_count--;
1930 *x1 = wx_stack_top->x1;
1931 *y1 = wx_stack_top->y1;
1932 *x2 = wx_stack_top->x2;
1933 *y2 = wx_stack_top->y2;
1934 *x3 = wx_stack_top->x3;
1935 *y3 = wx_stack_top->y3;
1936 *x4 = wx_stack_top->x4;
1937 *y4 = wx_stack_top->y4;
1938 return (1);
1939}
1940
1941static bool wx_spline_add_point(double x, double y)
1942{
1943 wxPoint *point = new wxPoint ;
1944 point->x = (int) x;
1945 point->y = (int) y;
1946 wx_spline_point_list.Append((wxObject*)point);
1947 return TRUE;
1948}
1949
1950static void wx_spline_draw_point_array(wxDC *dc)
1951{
1952 dc->DrawLines(&wx_spline_point_list, 0, 0 );
1953 wxNode *node = wx_spline_point_list.First();
1954 while (node)
1955 {
1956 wxPoint *point = (wxPoint *)node->Data();
1957 delete point;
1958 delete node;
1959 node = wx_spline_point_list.First();
1960 }
1961}
1962
b0e0d661 1963void wxWindowDC::DoDrawSpline( wxList *points )
c801d85f 1964{
223d09f6 1965 wxCHECK_RET( Ok(), wxT("invalid window dc") );
7d5af6fa 1966
c801d85f
KB
1967 wxPoint *p;
1968 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
1969 double x1, y1, x2, y2;
1970
1971 wxNode *node = points->First();
1972 p = (wxPoint *)node->Data();
1973
1974 x1 = p->x;
1975 y1 = p->y;
1976
1977 node = node->Next();
1978 p = (wxPoint *)node->Data();
1979
1980 x2 = p->x;
1981 y2 = p->y;
1982 cx1 = (double)((x1 + x2) / 2);
1983 cy1 = (double)((y1 + y2) / 2);
1984 cx2 = (double)((cx1 + x2) / 2);
1985 cy2 = (double)((cy1 + y2) / 2);
1986
1987 wx_spline_add_point(x1, y1);
1988
1989 while ((node = node->Next()) != NULL)
1990 {
1991 p = (wxPoint *)node->Data();
b0e0d661
VZ
1992 x1 = x2;
1993 y1 = y2;
1994 x2 = p->x;
1995 y2 = p->y;
c801d85f
KB
1996 cx4 = (double)(x1 + x2) / 2;
1997 cy4 = (double)(y1 + y2) / 2;
1998 cx3 = (double)(x1 + cx4) / 2;
1999 cy3 = (double)(y1 + cy4) / 2;
2000
2001 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
2002
b0e0d661
VZ
2003 cx1 = cx4;
2004 cy1 = cy4;
c801d85f
KB
2005 cx2 = (double)(cx1 + x2) / 2;
2006 cy2 = (double)(cy1 + y2) / 2;
2007 }
2008
2009 wx_spline_add_point( cx1, cy1 );
2010 wx_spline_add_point( x2, y2 );
2011
2012 wx_spline_draw_point_array( this );
903f689b 2013}
ec758a20 2014
b0e0d661 2015#endif // wxUSE_SPLINE
ec758a20
RR
2016
2017//-----------------------------------------------------------------------------
2018// wxPaintDC
2019//-----------------------------------------------------------------------------
2020
2021IMPLEMENT_DYNAMIC_CLASS(wxPaintDC,wxWindowDC)
2022
4bc67cc5 2023wxPaintDC::wxPaintDC()
ec758a20
RR
2024 : wxWindowDC()
2025{
2026}
2027
2028wxPaintDC::wxPaintDC( wxWindow *win )
2029 : wxWindowDC( win )
2030{
b6fa52db
RR
2031#if USE_PAINT_REGION
2032 if (!win->m_clipPaintRegion)
2033 return;
2034
e1208c31
RR
2035 m_paintClippingRegion = win->GetUpdateRegion();
2036 m_currentClippingRegion.Union( m_paintClippingRegion );
3d2d8da1 2037
e1208c31
RR
2038 gdk_gc_set_clip_region( m_penGC, m_paintClippingRegion.GetRegion() );
2039 gdk_gc_set_clip_region( m_brushGC, m_paintClippingRegion.GetRegion() );
2040 gdk_gc_set_clip_region( m_textGC, m_paintClippingRegion.GetRegion() );
2041 gdk_gc_set_clip_region( m_bgGC, m_paintClippingRegion.GetRegion() );
809934d2 2042#endif
ec758a20
RR
2043}
2044
2045//-----------------------------------------------------------------------------
2046// wxClientDC
2047//-----------------------------------------------------------------------------
2048
2049IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC)
2050
4bc67cc5 2051wxClientDC::wxClientDC()
ec758a20
RR
2052 : wxWindowDC()
2053{
2054}
2055
2056wxClientDC::wxClientDC( wxWindow *win )
2057 : wxWindowDC( win )
2058{
2059}
2060
3d2d8da1
RR
2061// ----------------------------------------------------------------------------
2062// wxDCModule
2063// ----------------------------------------------------------------------------
2064
2065class wxDCModule : public wxModule
2066{
2067public:
2068 bool OnInit();
2069 void OnExit();
2070
2071private:
2072 DECLARE_DYNAMIC_CLASS(wxDCModule)
2073};
2074
2075IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
2076
2077bool wxDCModule::OnInit()
2078{
2079 wxInitGCPool();
2080 return TRUE;
2081}
2082
2083void wxDCModule::OnExit()
2084{
2085 wxCleanUpGCPool();
2086}