]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/dcclient.cpp
No longer emit char events for shift/ctrl presses.
[wxWidgets.git] / src / gtk1 / dcclient.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: dcclient.cpp
3// Purpose:
4// Author: Robert Roebling
6f65e337 5// RCS-ID: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
b0e0d661 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"
f5368809 17#include <math.h>
c801d85f 18
83624f79
RR
19#include "gdk/gdk.h"
20#include "gtk/gtk.h"
21
c801d85f
KB
22//-----------------------------------------------------------------------------
23// local data
24//-----------------------------------------------------------------------------
25
26#include "bdiag.xbm"
27#include "fdiag.xbm"
28#include "cdiag.xbm"
29#include "horiz.xbm"
30#include "verti.xbm"
31#include "cross.xbm"
32#define num_hatches 6
33
34static GdkPixmap *hatches[num_hatches];
c67daf87 35static GdkPixmap **hatch_bitmap = (GdkPixmap **) NULL;
c801d85f
KB
36
37//-----------------------------------------------------------------------------
38// constants
39//-----------------------------------------------------------------------------
40
41#define RAD2DEG 57.2957795131
42
6f65e337
JS
43//-----------------------------------------------------------------------------
44// temporary implementation of the missing GDK function
45//-----------------------------------------------------------------------------
b0e0d661 46
6f65e337 47#include "gdk/gdkprivate.h"
b0e0d661
VZ
48
49void gdk_draw_bitmap (GdkDrawable *drawable,
50 GdkGC *gc,
51 GdkDrawable *src,
52 gint xsrc,
53 gint ysrc,
54 gint xdest,
55 gint ydest,
56 gint width,
57 gint height)
6f65e337 58{
265898fd
RR
59 GdkWindowPrivate *drawable_private;
60 GdkWindowPrivate *src_private;
61 GdkGCPrivate *gc_private;
62
63 g_return_if_fail (drawable != NULL);
64 g_return_if_fail (src != NULL);
65 g_return_if_fail (gc != NULL);
66
67 drawable_private = (GdkWindowPrivate*) drawable;
68 src_private = (GdkWindowPrivate*) src;
69 if (drawable_private->destroyed || src_private->destroyed)
70 return;
b0e0d661 71
265898fd
RR
72 gc_private = (GdkGCPrivate*) gc;
73
74 if (width == -1) width = src_private->width;
75 if (height == -1) height = src_private->height;
76
77 XCopyPlane( drawable_private->xdisplay,
b0e0d661
VZ
78 src_private->xwindow,
79 drawable_private->xwindow,
80 gc_private->xgc,
81 xsrc, ysrc,
82 width, height,
83 xdest, ydest,
84 1 );
6f65e337
JS
85}
86
c801d85f 87//-----------------------------------------------------------------------------
ec758a20 88// wxWindowDC
c801d85f
KB
89//-----------------------------------------------------------------------------
90
b0e0d661 91IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
c801d85f 92
4bc67cc5 93wxWindowDC::wxWindowDC()
c801d85f 94{
265898fd
RR
95 m_penGC = (GdkGC *) NULL;
96 m_brushGC = (GdkGC *) NULL;
97 m_textGC = (GdkGC *) NULL;
98 m_bgGC = (GdkGC *) NULL;
99 m_cmap = (GdkColormap *) NULL;
100 m_isMemDC = FALSE;
bbbbe360 101 m_owner = (wxWindow *)NULL;
903f689b 102}
c801d85f 103
ec758a20 104wxWindowDC::wxWindowDC( wxWindow *window )
c801d85f 105{
265898fd
RR
106 m_penGC = (GdkGC *) NULL;
107 m_brushGC = (GdkGC *) NULL;
108 m_textGC = (GdkGC *) NULL;
109 m_bgGC = (GdkGC *) NULL;
110 m_cmap = (GdkColormap *) NULL;
bbbbe360 111 m_owner = (wxWindow *)NULL;
265898fd 112
b0e0d661
VZ
113 if (!window)
114 return;
1e133b7d 115
a2053b27 116 GtkWidget *widget = window->m_wxwindow;
f03fc89f
VZ
117 if (!widget)
118 return;
1e133b7d 119
265898fd 120 m_window = widget->window;
1e133b7d
RR
121
122 /* not realized ? */
123 if (!m_window)
124 {
125 /* force realization */
126 gtk_widget_realize( widget );
127 m_window = widget->window;
128 }
129
130 /* still not realized ? */
b0e0d661
VZ
131 if (!m_window)
132 return;
1e133b7d 133
a2053b27
RR
134 if (window->m_wxwindow)
135 m_cmap = gtk_widget_get_colormap( window->m_wxwindow );
265898fd 136 else
a2053b27 137 m_cmap = gtk_widget_get_colormap( window->m_widget );
0180d5da 138
265898fd 139 m_isMemDC = FALSE;
0180d5da 140
265898fd 141 SetUpDC();
bbbbe360
RR
142
143 /* this must be done after SetUpDC, bacause SetUpDC calls the
144 repective SetBrush, SetPen, SetBackground etc functions
145 to set up the DC. SetBackground call m_owner->SetBackground
146 and this might not be desired as the standard dc background
147 is white whereas a window might assume gray to be the
148 standard (as e.g. wxStatusBar) */
76ed8f8d 149
bbbbe360 150 m_owner = window;
903f689b 151}
c801d85f 152
4bc67cc5 153wxWindowDC::~wxWindowDC()
c801d85f 154{
265898fd 155 Destroy();
903f689b 156}
c801d85f 157
b0e0d661 158void wxWindowDC::DoFloodFill( long WXUNUSED(x), long WXUNUSED(y),
463c1fa1 159 const wxColour &WXUNUSED(col), int WXUNUSED(style) )
c801d85f 160{
b0e0d661 161 wxFAIL_MSG( _T("wxWindowDC::DoFloodFill not implemented") );
903f689b 162}
c801d85f 163
b0e0d661 164bool wxWindowDC::DoGetPixel( long WXUNUSED(x1), long WXUNUSED(y1), wxColour *WXUNUSED(col) ) const
c801d85f 165{
b0e0d661 166 wxFAIL_MSG( _T("wxWindowDC::DoGetPixel not implemented") );
265898fd 167 return FALSE;
903f689b 168}
c801d85f 169
b0e0d661 170void wxWindowDC::DoDrawLine( long x1, long y1, long x2, long y2 )
c801d85f 171{
93c5dd39 172 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 173
265898fd
RR
174 if (m_pen.GetStyle() != wxTRANSPARENT)
175 {
176 gdk_draw_line( m_window, m_penGC,
177 XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
b0e0d661 178
ed880dd4
RR
179 CalcBoundingBox(x1, y1);
180 CalcBoundingBox(x2, y2);
265898fd 181 }
903f689b 182}
c801d85f 183
b0e0d661 184void wxWindowDC::DoCrossHair( long x, long y )
c801d85f 185{
93c5dd39 186 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 187
265898fd
RR
188 if (m_pen.GetStyle() != wxTRANSPARENT)
189 {
190 int w = 0;
191 int h = 0;
192 GetSize( &w, &h );
193 long xx = XLOG2DEV(x);
194 long yy = YLOG2DEV(y);
195 gdk_draw_line( m_window, m_penGC, 0, yy, XLOG2DEVREL(w), yy );
196 gdk_draw_line( m_window, m_penGC, xx, 0, xx, YLOG2DEVREL(h) );
197 }
903f689b 198}
c801d85f 199
b0e0d661
VZ
200void wxWindowDC::DoDrawArc( long x1, long y1, long x2, long y2,
201 long xc, long yc )
c801d85f 202{
93c5dd39 203 wxCHECK_RET( Ok(), _T("invalid window dc") );
265898fd
RR
204
205 long xx1 = XLOG2DEV(x1);
206 long yy1 = YLOG2DEV(y1);
207 long xx2 = XLOG2DEV(x2);
208 long yy2 = YLOG2DEV(y2);
0de9b5b2
RR
209 long xxc = XLOG2DEV(xc);
210 long yyc = YLOG2DEV(yc);
265898fd
RR
211 double dx = xx1 - xxc;
212 double dy = yy1 - yyc;
213 double radius = sqrt(dx*dx+dy*dy);
214 long r = (long)radius;
215 double radius1, radius2;
216
217 if (xx1 == xx2 && yy1 == yy2)
218 {
219 radius1 = 0.0;
220 radius2 = 360.0;
221 }
222 else
223 if (radius == 0.0)
224 {
225 radius1 = radius2 = 0.0;
226 }
227 else
228 {
229 radius1 = (xx1 - xxc == 0) ?
b0e0d661
VZ
230 (yy1 - yyc < 0) ? 90.0 : -90.0 :
231 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
265898fd 232 radius2 = (xx2 - xxc == 0) ?
b0e0d661
VZ
233 (yy2 - yyc < 0) ? 90.0 : -90.0 :
234 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
265898fd
RR
235 }
236 long alpha1 = long(radius1 * 64.0);
237 long alpha2 = long((radius2 - radius1) * 64.0);
238 while (alpha2 <= 0) alpha2 += 360*64;
239 while (alpha1 > 360*64) alpha1 -= 360*64;
240
241 if (m_brush.GetStyle() != wxTRANSPARENT)
242 gdk_draw_arc( m_window, m_brushGC, TRUE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
c801d85f 243
265898fd
RR
244 if (m_pen.GetStyle() != wxTRANSPARENT)
245 gdk_draw_arc( m_window, m_penGC, FALSE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
246
247 CalcBoundingBox (x1, y1);
248 CalcBoundingBox (x2, y2);
903f689b 249}
c801d85f 250
b0e0d661 251void wxWindowDC::DoDrawEllipticArc( long x, long y, long width, long height, double sa, double ea )
c801d85f 252{
93c5dd39 253 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 254
265898fd
RR
255 long xx = XLOG2DEV(x);
256 long yy = YLOG2DEV(y);
257 long ww = m_signX * XLOG2DEVREL(width);
258 long hh = m_signY * YLOG2DEVREL(height);
c801d85f 259
265898fd
RR
260 // CMB: handle -ve width and/or height
261 if (ww < 0) { ww = -ww; xx = xx - ww; }
262 if (hh < 0) { hh = -hh; yy = yy - hh; }
6f65e337 263
265898fd
RR
264 long start = long(sa * 64.0);
265 long end = long(ea * 64.0);
266 if (m_brush.GetStyle() != wxTRANSPARENT)
267 gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, start, end );
c801d85f 268
265898fd
RR
269 if (m_pen.GetStyle() != wxTRANSPARENT)
270 gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, ww, hh, start, end );
b0e0d661 271
265898fd
RR
272 CalcBoundingBox (x, y);
273 CalcBoundingBox (x + width, y + height);
903f689b 274}
c801d85f 275
b0e0d661 276void wxWindowDC::DoDrawPoint( long x, long y )
c801d85f 277{
93c5dd39 278 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 279
265898fd
RR
280 if (m_pen.GetStyle() != wxTRANSPARENT)
281 gdk_draw_point( m_window, m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
b0e0d661 282
265898fd 283 CalcBoundingBox (x, y);
903f689b 284}
c801d85f 285
b0e0d661 286void wxWindowDC::DoDrawLines( int n, wxPoint points[], long xoffset, long yoffset )
c801d85f 287{
93c5dd39 288 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 289
265898fd
RR
290 if (m_pen.GetStyle() == wxTRANSPARENT) return;
291 if (n <= 0) return;
c801d85f 292
265898fd
RR
293 CalcBoundingBox( points[0].x + xoffset, points[0].y + yoffset );
294
295 for (int i = 0; i < n-1; i++)
296 {
297 long x1 = XLOG2DEV(points[i].x + xoffset);
298 long x2 = XLOG2DEV(points[i+1].x + xoffset);
299 long y1 = YLOG2DEV(points[i].y + yoffset); // oh, what a waste
300 long y2 = YLOG2DEV(points[i+1].y + yoffset);
301 gdk_draw_line( m_window, m_penGC, x1, y1, x2, y2 );
b0e0d661 302
265898fd
RR
303 CalcBoundingBox( points[i+1].x + xoffset, points[i+1].y + yoffset );
304 }
903f689b 305}
c801d85f 306
b0e0d661 307void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], long xoffset, long yoffset, int WXUNUSED(fillStyle) )
cf7a7e13 308{
93c5dd39 309 wxCHECK_RET( Ok(), _T("invalid window dc") );
cf7a7e13 310
4bc67cc5 311 if (n <= 0) return;
265898fd
RR
312
313 GdkPoint *gdkpoints = new GdkPoint[n+1];
314 int i;
315 for (i = 0 ; i < n ; i++)
316 {
317 gdkpoints[i].x = XLOG2DEV(points[i].x + xoffset);
318 gdkpoints[i].y = YLOG2DEV(points[i].y + yoffset);
b0e0d661 319
265898fd
RR
320 CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset );
321 }
322
323 if (m_brush.GetStyle() != wxTRANSPARENT)
324 gdk_draw_polygon (m_window, m_brushGC, TRUE, gdkpoints, n);
325
326 // To do: Fillstyle
327
328 if (m_pen.GetStyle() != wxTRANSPARENT)
329 for (i = 0 ; i < n ; i++)
b0e0d661 330 {
265898fd 331 gdk_draw_line( m_window, m_penGC,
b0e0d661
VZ
332 gdkpoints[i%n].x,
333 gdkpoints[i%n].y,
334 gdkpoints[(i+1)%n].x,
335 gdkpoints[(i+1)%n].y);
265898fd 336 }
b0e0d661 337
265898fd 338 delete[] gdkpoints;
903f689b 339}
c801d85f 340
b0e0d661 341void wxWindowDC::DoDrawRectangle( long x, long y, long width, long height )
c801d85f 342{
93c5dd39 343 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 344
265898fd
RR
345 long xx = XLOG2DEV(x);
346 long yy = YLOG2DEV(y);
347 long ww = m_signX * XLOG2DEVREL(width);
348 long hh = m_signY * YLOG2DEVREL(height);
c801d85f 349
265898fd
RR
350 // CMB: draw nothing if transformed w or h is 0
351 if (ww == 0 || hh == 0) return;
6f65e337 352
265898fd
RR
353 // CMB: handle -ve width and/or height
354 if (ww < 0) { ww = -ww; xx = xx - ww; }
355 if (hh < 0) { hh = -hh; yy = yy - hh; }
6f65e337 356
265898fd
RR
357 if (m_brush.GetStyle() != wxTRANSPARENT)
358 gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh );
c801d85f 359
265898fd
RR
360 if (m_pen.GetStyle() != wxTRANSPARENT)
361 gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-1, hh-1 );
362
363 CalcBoundingBox( x, y );
364 CalcBoundingBox( x + width, y + height );
903f689b 365}
c801d85f 366
b0e0d661 367void wxWindowDC::DoDrawRoundedRectangle( long x, long y, long width, long height, double radius )
c801d85f 368{
93c5dd39 369 wxCHECK_RET( Ok(), _T("invalid window dc") );
265898fd
RR
370
371 if (radius < 0.0) radius = - radius * ((width < height) ? width : height);
372
373 long xx = XLOG2DEV(x);
374 long yy = YLOG2DEV(y);
375 long ww = m_signX * XLOG2DEVREL(width);
376 long hh = m_signY * YLOG2DEVREL(height);
377 long rr = XLOG2DEVREL((long)radius);
378
379 // CMB: handle -ve width and/or height
380 if (ww < 0) { ww = -ww; xx = xx - ww; }
381 if (hh < 0) { hh = -hh; yy = yy - hh; }
382
383 // CMB: if radius is zero use DrawRectangle() instead to avoid
384 // X drawing errors with small radii
385 if (rr == 0)
386 {
387 DrawRectangle( x, y, width, height );
388 return;
389 }
390
391 // CMB: draw nothing if transformed w or h is 0
392 if (ww == 0 || hh == 0) return;
393
394 // CMB: adjust size if outline is drawn otherwise the result is
395 // 1 pixel too wide and high
396 if (m_pen.GetStyle() != wxTRANSPARENT)
397 {
398 ww--;
399 hh--;
400 }
401
402 // CMB: ensure dd is not larger than rectangle otherwise we
403 // get an hour glass shape
404 long dd = 2 * rr;
405 if (dd > ww) dd = ww;
406 if (dd > hh) dd = hh;
407 rr = dd / 2;
408
409 if (m_brush.GetStyle() != wxTRANSPARENT)
410 {
411 gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx+rr, yy, ww-dd+1, hh );
412 gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy+rr, ww, hh-dd+1 );
413 gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, dd, dd, 90*64, 90*64 );
414 gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
415 gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
416 gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
417 }
418
419 if (m_pen.GetStyle() != wxTRANSPARENT)
420 {
421 gdk_draw_line( m_window, m_penGC, xx+rr, yy, xx+ww-rr, yy );
422 gdk_draw_line( m_window, m_penGC, xx+rr, yy+hh, xx+ww-rr, yy+hh );
423 gdk_draw_line( m_window, m_penGC, xx, yy+rr, xx, yy+hh-rr );
424 gdk_draw_line( m_window, m_penGC, xx+ww, yy+rr, xx+ww, yy+hh-rr );
425 gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, dd, dd, 90*64, 90*64 );
426 gdk_draw_arc( m_window, m_penGC, FALSE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
427 gdk_draw_arc( m_window, m_penGC, FALSE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
428 gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
429 }
430
431 // this ignores the radius
432 CalcBoundingBox( x, y );
433 CalcBoundingBox( x + width, y + height );
903f689b 434}
c801d85f 435
b0e0d661 436void wxWindowDC::DoDrawEllipse( long x, long y, long width, long height )
c801d85f 437{
93c5dd39 438 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 439
265898fd
RR
440 long xx = XLOG2DEV(x);
441 long yy = YLOG2DEV(y);
442 long ww = m_signX * XLOG2DEVREL(width);
443 long hh = m_signY * YLOG2DEVREL(height);
6f65e337 444
265898fd
RR
445 // CMB: handle -ve width and/or height
446 if (ww < 0) { ww = -ww; xx = xx - ww; }
447 if (hh < 0) { hh = -hh; yy = yy - hh; }
c801d85f 448
265898fd
RR
449 if (m_brush.GetStyle() != wxTRANSPARENT)
450 gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, 0, 360*64 );
c801d85f 451
265898fd
RR
452 if (m_pen.GetStyle() != wxTRANSPARENT)
453 gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, ww, hh, 0, 360*64 );
b0e0d661 454
ed880dd4 455 CalcBoundingBox( x - width, y - height );
265898fd 456 CalcBoundingBox( x + width, y + height );
903f689b 457}
c801d85f 458
b0e0d661 459void wxWindowDC::DoDrawIcon( const wxIcon &icon, long x, long y )
c801d85f 460{
b0e0d661
VZ
461 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
462 DoDrawBitmap( (const wxBitmap&)icon, x, y, (bool)TRUE );
903f689b 463}
c801d85f 464
b0e0d661
VZ
465void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
466 long x, long y,
467 bool useMask )
4bc67cc5 468{
93c5dd39 469 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 470
b0e0d661 471 wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
6e13c196
RR
472
473 /* scale/translate size and position */
c801d85f 474
265898fd
RR
475 int xx = XLOG2DEV(x);
476 int yy = YLOG2DEV(y);
c801d85f 477
4bc67cc5
RR
478 int w = bitmap.GetWidth();
479 int h = bitmap.GetHeight();
c801d85f 480
4bc67cc5
RR
481 int ww = XLOG2DEVREL(w);
482 int hh = YLOG2DEVREL(h);
483
6e13c196
RR
484 /* scale bitmap if required */
485
4bc67cc5
RR
486 wxBitmap use_bitmap;
487
488 if ((w != ww) || (h != hh))
265898fd 489 {
4bc67cc5 490 wxImage image( bitmap );
b0e0d661
VZ
491 image = image.Scale( ww, hh );
492
493 use_bitmap = image.ConvertToBitmap();
265898fd 494 }
4bc67cc5 495 else
265898fd 496 {
4bc67cc5 497 use_bitmap = bitmap;
265898fd
RR
498 }
499
6e13c196
RR
500 /* apply mask if any */
501
463c1fa1 502 GdkBitmap *mask = (GdkBitmap *) NULL;
4bc67cc5 503 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
463c1fa1
RR
504
505 if (useMask && mask)
506 {
507 gdk_gc_set_clip_mask( m_penGC, mask );
508 gdk_gc_set_clip_origin( m_penGC, xx, yy );
509 }
510
6e13c196
RR
511 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
512
4bc67cc5 513 GdkPixmap *pm = use_bitmap.GetPixmap();
6e13c196
RR
514 if (pm)
515 {
516 gdk_draw_pixmap( m_window, m_penGC, pm, 0, 0, xx, yy, -1, -1 );
517 }
518 else
519 {
520 GdkBitmap *bm = use_bitmap.GetBitmap();
521 if (bm)
522 {
523 gdk_draw_bitmap( m_window, m_penGC, bm, 0, 0, xx, yy, -1, -1 );
b0e0d661 524 }
6e13c196
RR
525 }
526
527 /* remove mask again if any */
528
463c1fa1
RR
529 if (useMask && mask)
530 {
531 gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
532 gdk_gc_set_clip_origin( m_penGC, 0, 0 );
533 }
534
535 CalcBoundingBox( x, y );
4bc67cc5 536 CalcBoundingBox( x + w, y + h );
463c1fa1
RR
537}
538
b0e0d661
VZ
539bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height,
540 wxDC *source, long xsrc, long ysrc,
541 int logical_func, bool useMask )
c801d85f 542{
6e13c196
RR
543 /* this is the nth try to get this utterly useless function to
544 work. it now completely ignores the scaling or translation
545 of the source dc, but scales correctly on the target dc and
546 knows about possible mask information in a memory dc. */
547
93c5dd39 548 wxCHECK_MSG( Ok(), FALSE, _T("invalid window dc") );
e23d0e95 549
93c5dd39 550 wxCHECK_MSG( source, FALSE, _T("invalid source dc") );
6e13c196
RR
551
552 wxClientDC *srcDC = (wxClientDC*)source;
553 wxMemoryDC *memDC = (wxMemoryDC*)source;
554
555 bool use_bitmap_method = FALSE;
556
557 if (srcDC->m_isMemDC)
558 {
b0e0d661
VZ
559 if (!memDC->m_selected.Ok()) return FALSE;
560
6e13c196 561 /* we use the "XCopyArea" way to copy a memory dc into
b0e0d661
VZ
562 y different window if the memory dc BOTH
563 a) doesn't have any mask or its mask isn't used
564 b) it is clipped
565 c) is not 1-bit */
6e13c196 566
f234c60c 567 if (useMask && (memDC->m_selected.GetMask()))
b0e0d661
VZ
568 {
569 /* we HAVE TO use the direct way for memory dcs
570 that have mask since the XCopyArea doesn't know
571 about masks */
572 use_bitmap_method = TRUE;
573 }
574 else if (memDC->m_selected.GetDepth() == 1)
575 {
576 /* we HAVE TO use the direct way for memory dcs
577 that are bitmaps because XCopyArea doesn't cope
578 with different bit depths */
579 use_bitmap_method = TRUE;
580 }
581 else if ((xsrc == 0) && (ysrc == 0) &&
582 (width == memDC->m_selected.GetWidth()) &&
583 (height == memDC->m_selected.GetHeight()))
584 {
585 /* we SHOULD use the direct way if all of the bitmap
586 in the memory dc is copied in which case XCopyArea
587 wouldn't be able able to boost performace by reducing
588 the area to be scaled */
589 use_bitmap_method = TRUE;
590 }
591 else
592 {
593 use_bitmap_method = FALSE;
594 }
6e13c196
RR
595 }
596
265898fd
RR
597 CalcBoundingBox( xdest, ydest );
598 CalcBoundingBox( xdest + width, ydest + height );
599
4bc67cc5
RR
600 int old_logical_func = m_logicalFunction;
601 SetLogicalFunction( logical_func );
602
6e13c196 603 if (use_bitmap_method)
6f65e337 604 {
6e13c196
RR
605 /* scale/translate bitmap size */
606
b0e0d661
VZ
607 long bm_width = memDC->m_selected.GetWidth();
608 long bm_height = memDC->m_selected.GetHeight();
609
610 long bm_ww = XLOG2DEVREL( bm_width );
611 long bm_hh = YLOG2DEVREL( bm_height );
612
6e13c196
RR
613 /* scale bitmap if required */
614
615 wxBitmap use_bitmap;
616
617 if ((bm_width != bm_ww) || (bm_height != bm_hh))
618 {
619 wxImage image( memDC->m_selected );
b0e0d661
VZ
620 image = image.Scale( bm_ww, bm_hh );
621
622 use_bitmap = image.ConvertToBitmap();
6e13c196
RR
623 }
624 else
e23d0e95 625 {
6e13c196
RR
626 use_bitmap = memDC->m_selected;
627 }
b0e0d661 628
6e13c196
RR
629 /* scale/translate size and position */
630
631 long xx = XLOG2DEV(xdest);
632 long yy = YLOG2DEV(ydest);
b0e0d661
VZ
633
634 long ww = XLOG2DEVREL(width);
635 long hh = YLOG2DEVREL(height);
636
6e13c196 637 /* apply mask if any */
e23d0e95 638
6e13c196
RR
639 GdkBitmap *mask = (GdkBitmap *) NULL;
640 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
e23d0e95 641
6e13c196
RR
642 if (useMask && mask)
643 {
644 gdk_gc_set_clip_mask( m_penGC, mask );
645 gdk_gc_set_clip_origin( m_penGC, xx, yy );
e23d0e95 646 }
b0e0d661 647
6e13c196
RR
648 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
649
650 GdkPixmap *pm = use_bitmap.GetPixmap();
651 if (pm)
265898fd 652 {
f234c60c 653 gdk_draw_pixmap( m_window, m_penGC, pm, xsrc, ysrc, xx, yy, ww, hh );
6e13c196
RR
654 }
655 else
656 {
657 GdkBitmap *bm = use_bitmap.GetBitmap();
658 if (bm)
659 {
b0e0d661
VZ
660 /* we use the textGC here because blitting a bitmap is done
661 using the current text colour */
f234c60c 662 gdk_draw_bitmap( m_window, m_textGC, bm, xsrc, ysrc, xx, yy, ww, hh );
b0e0d661 663 }
6e13c196 664 }
df875e59 665
6e13c196 666 /* remove mask again if any */
df875e59 667
6e13c196
RR
668 if (useMask && mask)
669 {
670 gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
671 gdk_gc_set_clip_origin( m_penGC, 0, 0 );
265898fd 672 }
6f65e337 673 }
6e13c196
RR
674 else /* use_bitmap_method */
675 {
676 /* scale/translate size and position */
677
678 long xx = XLOG2DEV(xdest);
679 long yy = YLOG2DEV(ydest);
b0e0d661
VZ
680
681 long ww = XLOG2DEVREL(width);
682 long hh = YLOG2DEVREL(height);
683
6e13c196 684 if ((width != ww) || (height != hh))
b0e0d661
VZ
685 {
686 /* draw source window into a bitmap as we cannot scale
687 a window in contrast to a bitmap. this would actually
688 work with memory dcs as well, but we'd lose the mask
689 information and waste one step in this process since
690 a memory already has a bitmap. all this is slightly
691 inefficient as we could take an XImage directly from
692 an X window, but we'd then also have to care that
693 the window is not outside the screen (in which case
694 we'd get a BadMatch or what not).
695 Is a double XGetImage and combined XGetPixel and
696 XPutPixel really faster? I'm not sure. look at wxXt
697 for a different implementation of the same problem. */
6e13c196 698
b0e0d661
VZ
699 wxBitmap bitmap( width, height );
700 gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
6e13c196 701 srcDC->GetWindow(),
b0e0d661
VZ
702 xsrc, ysrc, width, height );
703
704 /* scale image */
705
6e13c196 706 wxImage image( bitmap );
b0e0d661
VZ
707 image = image.Scale( ww, hh );
708
709 /* convert to bitmap */
710
711 bitmap = image.ConvertToBitmap();
712
713 /* draw scaled bitmap */
714
6e13c196 715 gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
b0e0d661
VZ
716
717 }
718 else
719 {
720 /* no scaling and not a memory dc with a mask either */
721
6e13c196
RR
722 gdk_window_copy_area( m_window, m_penGC, xx, yy,
723 srcDC->GetWindow(),
724 xsrc, ysrc, width, height );
b0e0d661 725 }
6e13c196 726 }
c801d85f 727
4bc67cc5
RR
728 SetLogicalFunction( old_logical_func );
729 return TRUE;
903f689b 730}
c801d85f 731
b0e0d661 732void wxWindowDC::DoDrawText( const wxString &text, long x, long y )
c801d85f 733{
93c5dd39 734 wxCHECK_RET( Ok(), _T("invalid window dc") );
18a2fa37 735
265898fd 736 GdkFont *font = m_font.GetInternalFont( m_scaleY );
6f65e337 737
265898fd
RR
738 x = XLOG2DEV(x);
739 y = YLOG2DEV(y);
18a2fa37 740
bbbbe360 741 /* CMB 21/5/98: draw text background if mode is wxSOLID */
265898fd
RR
742 if (m_backgroundMode == wxSOLID)
743 {
93c5dd39 744 long width = gdk_string_width( font, text.mbc_str() );
265898fd
RR
745 long height = font->ascent + font->descent;
746 gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
747 gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
748 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
749 }
93c5dd39 750 gdk_draw_string( m_window, font, m_textGC, x, y + font->ascent, text.mbc_str() );
18a2fa37 751
bbbbe360
RR
752 /* CMB 17/7/98: simple underline: ignores scaling and underlying
753 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
754 properties (see wxXt implementation) */
265898fd
RR
755 if (m_font.GetUnderlined())
756 {
93c5dd39 757 long width = gdk_string_width( font, text.mbc_str() );
265898fd
RR
758 long ul_y = y + font->ascent;
759 if (font->descent > 0) ul_y++;
760 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
761 }
762
763 long w, h;
764 GetTextExtent (text, &w, &h);
765 CalcBoundingBox (x + w, y + h);
766 CalcBoundingBox (x, y);
903f689b 767}
c801d85f 768
ec758a20 769void wxWindowDC::GetTextExtent( const wxString &string, long *width, long *height,
b0e0d661
VZ
770 long *descent, long *externalLeading,
771 wxFont *theFont ) const
c801d85f 772{
265898fd
RR
773 wxFont fontToUse = m_font;
774 if (theFont) fontToUse = *theFont;
c33c4050 775
265898fd 776 GdkFont *font = fontToUse.GetInternalFont( m_scaleY );
93c5dd39 777 if (width) (*width) = long(gdk_string_width( font, string.mbc_str() ) / m_scaleX);
265898fd
RR
778 if (height) (*height) = long((font->ascent + font->descent) / m_scaleY);
779 if (descent) (*descent) = long(font->descent / m_scaleY);
780 if (externalLeading) (*externalLeading) = 0; // ??
903f689b 781}
c801d85f 782
b0e0d661 783long wxWindowDC::GetCharWidth() const
c801d85f 784{
265898fd
RR
785 GdkFont *font = m_font.GetInternalFont( m_scaleY );
786 return long(gdk_string_width( font, "H" ) / m_scaleX);
903f689b 787}
c801d85f 788
b0e0d661 789long wxWindowDC::GetCharHeight() const
c801d85f 790{
265898fd
RR
791 GdkFont *font = m_font.GetInternalFont( m_scaleY );
792 return long((font->ascent + font->descent) / m_scaleY);
903f689b 793}
c801d85f 794
4bc67cc5 795void wxWindowDC::Clear()
c801d85f 796{
93c5dd39 797 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 798
f234c60c
RR
799 /* - we either are a memory dc or have a window as the
800 owner. anything else shouldn't happen.
801 - we don't use gdk_window_clear() as we don't set
802 the window's background colour anymore. it is too
803 much pain to keep the DC's and the window's back-
804 ground colour in synch. */
805
806 if (m_owner)
265898fd 807 {
f234c60c
RR
808 int width,height;
809 m_owner->GetSize( &width, &height );
810 gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height );
b0e0d661 811 return;
265898fd 812 }
f234c60c
RR
813
814 if (m_isMemDC)
265898fd
RR
815 {
816 int width,height;
817 GetSize( &width, &height );
818 gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height );
b0e0d661 819 return;
265898fd 820 }
903f689b 821}
c801d85f 822
ec758a20 823void wxWindowDC::SetFont( const wxFont &font )
c801d85f 824{
265898fd 825 m_font = font;
903f689b 826}
c801d85f 827
ec758a20 828void wxWindowDC::SetPen( const wxPen &pen )
c801d85f 829{
93c5dd39 830 wxCHECK_RET( Ok(), _T("invalid window dc") );
4bc67cc5 831
265898fd
RR
832 if (m_pen == pen) return;
833
834 m_pen = pen;
835
836 if (!m_pen.Ok()) return;
837
838 gint width = m_pen.GetWidth();
839 // CMB: if width is non-zero scale it with the dc
840 if (width <= 0)
841 {
842 width = 1;
843 }
844 else
845 {
846 // X doesn't allow different width in x and y and so we take
847 // the average
848 double w = 0.5 + (abs(XLOG2DEVREL(width)) + abs(YLOG2DEVREL(width))) / 2.0;
849 width = (int)w;
850 }
851
852 GdkLineStyle lineStyle = GDK_LINE_SOLID;
853 switch (m_pen.GetStyle())
854 {
855 case wxSOLID: { lineStyle = GDK_LINE_SOLID; break; }
856 case wxDOT: { lineStyle = GDK_LINE_ON_OFF_DASH; break; }
857 case wxLONG_DASH: { lineStyle = GDK_LINE_ON_OFF_DASH; break; }
858 case wxSHORT_DASH: { lineStyle = GDK_LINE_ON_OFF_DASH; break; }
859 case wxDOT_DASH: { lineStyle = GDK_LINE_DOUBLE_DASH; break; }
860 }
861
862 GdkCapStyle capStyle = GDK_CAP_ROUND;
863 switch (m_pen.GetCap())
864 {
865 case wxCAP_ROUND: { capStyle = (width <= 1) ? GDK_CAP_NOT_LAST : GDK_CAP_ROUND; break; }
866 case wxCAP_PROJECTING: { capStyle = GDK_CAP_PROJECTING; break; }
867 case wxCAP_BUTT: { capStyle = GDK_CAP_BUTT; break; }
868 }
869
870 GdkJoinStyle joinStyle = GDK_JOIN_ROUND;
871 switch (m_pen.GetJoin())
872 {
873 case wxJOIN_BEVEL: { joinStyle = GDK_JOIN_BEVEL; break; }
874 case wxJOIN_ROUND: { joinStyle = GDK_JOIN_ROUND; break; }
875 case wxJOIN_MITER: { joinStyle = GDK_JOIN_MITER; break; }
876 }
877
878 gdk_gc_set_line_attributes( m_penGC, width, lineStyle, capStyle, joinStyle );
879
880 m_pen.GetColour().CalcPixel( m_cmap );
881 gdk_gc_set_foreground( m_penGC, m_pen.GetColour().GetColor() );
903f689b 882}
c801d85f 883
ec758a20 884void wxWindowDC::SetBrush( const wxBrush &brush )
c801d85f 885{
93c5dd39 886 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 887
265898fd 888 if (m_brush == brush) return;
c801d85f 889
265898fd 890 m_brush = brush;
c801d85f 891
265898fd 892 if (!m_brush.Ok()) return;
c801d85f 893
265898fd
RR
894 m_brush.GetColour().CalcPixel( m_cmap );
895 gdk_gc_set_foreground( m_brushGC, m_brush.GetColour().GetColor() );
c801d85f 896
265898fd
RR
897 GdkFill fillStyle = GDK_SOLID;
898 switch (m_brush.GetStyle())
899 {
900 case wxSOLID:
901 case wxTRANSPARENT:
902 break;
903 default:
904 fillStyle = GDK_STIPPLED;
905 }
c801d85f 906
265898fd 907 gdk_gc_set_fill( m_brushGC, fillStyle );
c801d85f 908
4fcd73bd 909 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
265898fd 910 {
4fcd73bd
RR
911 if (m_brush.GetStipple()->GetPixmap())
912 gdk_gc_set_stipple( m_brushGC, m_brush.GetStipple()->GetPixmap() );
b0e0d661 913 else
4fcd73bd 914 gdk_gc_set_stipple( m_brushGC, m_brush.GetStipple()->GetBitmap() );
265898fd
RR
915 }
916
917 if (IS_HATCH(m_brush.GetStyle()))
918 {
919 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
920 gdk_gc_set_stipple( m_brushGC, hatches[num] );
921 }
903f689b 922}
c801d85f 923
ec758a20 924void wxWindowDC::SetBackground( const wxBrush &brush )
46dc76ba 925{
bbbbe360
RR
926 /* CMB 21/7/98: Added SetBackground. Sets background brush
927 * for Clear() and bg colour for shapes filled with cross-hatch brush */
4bc67cc5 928
93c5dd39 929 wxCHECK_RET( Ok(), _T("invalid window dc") );
46dc76ba 930
265898fd 931 if (m_backgroundBrush == brush) return;
46dc76ba 932
265898fd 933 m_backgroundBrush = brush;
46dc76ba 934
265898fd 935 if (!m_backgroundBrush.Ok()) return;
46dc76ba 936
265898fd
RR
937 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
938 gdk_gc_set_background( m_brushGC, m_backgroundBrush.GetColour().GetColor() );
a802c3a1 939 gdk_gc_set_background( m_penGC, m_backgroundBrush.GetColour().GetColor() );
031b2a7b 940 gdk_gc_set_background( m_bgGC, m_backgroundBrush.GetColour().GetColor() );
265898fd 941 gdk_gc_set_foreground( m_bgGC, m_backgroundBrush.GetColour().GetColor() );
46dc76ba 942
265898fd
RR
943 GdkFill fillStyle = GDK_SOLID;
944 switch (m_backgroundBrush.GetStyle())
945 {
bbbbe360
RR
946 case wxSOLID:
947 case wxTRANSPARENT:
948 break;
949 default:
950 fillStyle = GDK_STIPPLED;
265898fd 951 }
46dc76ba 952
265898fd 953 gdk_gc_set_fill( m_bgGC, fillStyle );
46dc76ba 954
265898fd
RR
955 if (m_backgroundBrush.GetStyle() == wxSTIPPLE)
956 {
957 gdk_gc_set_stipple( m_bgGC, m_backgroundBrush.GetStipple()->GetPixmap() );
958 }
46dc76ba 959
265898fd
RR
960 if (IS_HATCH(m_backgroundBrush.GetStyle()))
961 {
962 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
963 gdk_gc_set_stipple( m_bgGC, hatches[num] );
bbbbe360 964 }
903f689b 965}
46dc76ba 966
ec758a20 967void wxWindowDC::SetLogicalFunction( int function )
c801d85f 968{
93c5dd39 969 wxCHECK_RET( Ok(), _T("invalid window dc") );
4bc67cc5 970
265898fd 971 if (m_logicalFunction == function) return;
4bc67cc5 972
265898fd
RR
973 GdkFunction mode = GDK_COPY;
974 switch (function)
975 {
c96faa7c
RR
976 case wxXOR: mode = GDK_INVERT; break;
977 case wxINVERT: mode = GDK_INVERT; break;
978#if (GDK_MINOR_VERSION > 0)
979 case wxOR_REVERSE: mode = GDK_OR_REVERSE; break;
980 case wxAND_REVERSE: mode = GDK_AND_REVERSE; break;
981 case wxCLEAR: mode = GDK_CLEAR; break;
982 case wxSET: mode = GDK_SET; break;
983 case wxOR_INVERT: mode = GDK_OR_INVERT; break;
984 case wxAND: mode = GDK_AND; break;
985 case wxOR: mode = GDK_OR; break;
986 case wxEQUIV: mode = GDK_EQUIV; break;
987 case wxNAND: mode = GDK_NAND; break;
988 case wxAND_INVERT: mode = GDK_AND_INVERT; break;
989/* ? wxSRC_INVERT GDK_AND_REVERSE, GDK_OR_REVERSE, GDK_OR_INVERT */
990#endif
265898fd
RR
991 default: break;
992 }
4bc67cc5 993
265898fd
RR
994 m_logicalFunction = function;
995 gdk_gc_set_function( m_penGC, mode );
996 gdk_gc_set_function( m_brushGC, mode );
3bc755fc 997 gdk_gc_set_function( m_textGC, mode );
903f689b 998}
c801d85f 999
ec758a20 1000void wxWindowDC::SetTextForeground( const wxColour &col )
c801d85f 1001{
93c5dd39 1002 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 1003
265898fd 1004 if (m_textForegroundColour == col) return;
c801d85f 1005
265898fd
RR
1006 m_textForegroundColour = col;
1007 if (!m_textForegroundColour.Ok()) return;
c801d85f 1008
265898fd
RR
1009 m_textForegroundColour.CalcPixel( m_cmap );
1010 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
903f689b 1011}
c801d85f 1012
ec758a20 1013void wxWindowDC::SetTextBackground( const wxColour &col )
c801d85f 1014{
93c5dd39 1015 wxCHECK_RET( Ok(), _T("invalid window dc") );
c801d85f 1016
265898fd 1017 if (m_textBackgroundColour == col) return;
c801d85f 1018
265898fd
RR
1019 m_textBackgroundColour = col;
1020 if (!m_textBackgroundColour.Ok()) return;
c801d85f 1021
265898fd
RR
1022 m_textBackgroundColour.CalcPixel( m_cmap );
1023 gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() );
903f689b 1024}
c801d85f 1025
ec758a20 1026void wxWindowDC::SetBackgroundMode( int mode )
c801d85f 1027{
93c5dd39 1028 wxCHECK_RET( Ok(), _T("invalid window dc") );
4bc67cc5 1029
265898fd 1030 m_backgroundMode = mode;
46dc76ba 1031
265898fd
RR
1032 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1033 // transparent/solid background mode
4bc67cc5 1034
265898fd
RR
1035 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1036 {
1037 gdk_gc_set_fill( m_brushGC,
1038 (m_backgroundMode == wxTRANSPARENT) ? GDK_STIPPLED : GDK_OPAQUE_STIPPLED);
1039 }
903f689b 1040}
c801d85f 1041
ec758a20 1042void wxWindowDC::SetPalette( const wxPalette& WXUNUSED(palette) )
c801d85f 1043{
93c5dd39 1044 wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") );
903f689b 1045}
c801d85f 1046
b0e0d661 1047void wxWindowDC::DoSetClippingRegion( long x, long y, long width, long height )
c801d85f 1048{
93c5dd39 1049 wxCHECK_RET( Ok(), _T("invalid window dc") );
4bc67cc5 1050
089e55d6 1051 wxDC::DoSetClippingRegion( x, y, width, height );
c801d85f 1052
265898fd
RR
1053 GdkRectangle rect;
1054 rect.x = XLOG2DEV(x);
1055 rect.y = YLOG2DEV(y);
1056 rect.width = XLOG2DEVREL(width);
1057 rect.height = YLOG2DEVREL(height);
1058 gdk_gc_set_clip_rectangle( m_penGC, &rect );
1059 gdk_gc_set_clip_rectangle( m_brushGC, &rect );
1060 gdk_gc_set_clip_rectangle( m_textGC, &rect );
1061 gdk_gc_set_clip_rectangle( m_bgGC, &rect );
903f689b 1062}
c801d85f 1063
b0e0d661 1064void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion &region )
463c1fa1 1065{
93c5dd39 1066 wxCHECK_RET( Ok(), _T("invalid window dc") );
4bc67cc5 1067
463c1fa1
RR
1068 if (region.Empty())
1069 {
1070 DestroyClippingRegion();
1071 return;
1072 }
1073
1074 gdk_gc_set_clip_region( m_penGC, region.GetRegion() );
1075 gdk_gc_set_clip_region( m_brushGC, region.GetRegion() );
1076 gdk_gc_set_clip_region( m_textGC, region.GetRegion() );
1077 gdk_gc_set_clip_region( m_bgGC, region.GetRegion() );
1078}
1079
4bc67cc5 1080void wxWindowDC::DestroyClippingRegion()
c801d85f 1081{
93c5dd39 1082 wxCHECK_RET( Ok(), _T("invalid window dc") );
4bc67cc5 1083
265898fd 1084 wxDC::DestroyClippingRegion();
c801d85f 1085
265898fd
RR
1086 gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL );
1087 gdk_gc_set_clip_rectangle( m_brushGC, (GdkRectangle *) NULL );
1088 gdk_gc_set_clip_rectangle( m_textGC, (GdkRectangle *) NULL );
1089 gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL );
903f689b 1090}
c801d85f 1091
4bc67cc5 1092void wxWindowDC::SetUpDC()
c801d85f 1093{
265898fd
RR
1094 Destroy();
1095 m_ok = TRUE;
1096 m_logicalFunction = wxCOPY;
1097 m_penGC = gdk_gc_new( m_window );
1098 m_brushGC = gdk_gc_new( m_window );
1099 m_textGC = gdk_gc_new( m_window );
1100 m_bgGC = gdk_gc_new( m_window );
a802c3a1
RR
1101
1102 wxColour tmp_col( m_textForegroundColour );
1103 m_textForegroundColour = wxNullColour;
1104 SetTextForeground( tmp_col );
1105 tmp_col = m_textBackgroundColour;
1106 m_textBackgroundColour = wxNullColour;
1107 SetTextBackground( tmp_col );
031b2a7b
RR
1108
1109 wxPen tmp_pen( m_pen );
1110 m_pen = wxNullPen;
1111 SetPen( tmp_pen );
1112
1113 wxFont tmp_font( m_font );
1114 m_font = wxNullFont;
1115 SetFont( tmp_font );
1116
1117 wxBrush tmp_brush( m_brush );
1118 m_brush = wxNullBrush;
1119 SetBrush( tmp_brush );
1120
1121 tmp_brush = m_backgroundBrush;
1122 m_backgroundBrush = wxNullBrush;
1123 SetBackground( tmp_brush );
265898fd 1124
265898fd
RR
1125 if (!hatch_bitmap)
1126 {
1127 hatch_bitmap = hatches;
1128 hatch_bitmap[0] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, bdiag_bits, bdiag_width, bdiag_height );
1129 hatch_bitmap[1] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, cdiag_bits, cdiag_width, cdiag_height );
1130 hatch_bitmap[2] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, fdiag_bits, fdiag_width, fdiag_height );
1131 hatch_bitmap[3] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, cross_bits, cross_width, cross_height );
1132 hatch_bitmap[4] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, horiz_bits, horiz_width, horiz_height );
1133 hatch_bitmap[5] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, verti_bits, verti_width, verti_height );
1134 }
903f689b 1135}
c801d85f 1136
4bc67cc5 1137void wxWindowDC::Destroy()
dbf858b5 1138{
265898fd
RR
1139 if (m_penGC) gdk_gc_unref( m_penGC );
1140 m_penGC = (GdkGC*) NULL;
1141 if (m_brushGC) gdk_gc_unref( m_brushGC );
1142 m_brushGC = (GdkGC*) NULL;
1143 if (m_textGC) gdk_gc_unref( m_textGC );
1144 m_textGC = (GdkGC*) NULL;
1145 if (m_bgGC) gdk_gc_unref( m_bgGC );
1146 m_bgGC = (GdkGC*) NULL;
dbf858b5
RR
1147}
1148
b0e0d661
VZ
1149// Resolution in pixels per logical inch
1150wxSize wxWindowDC::GetPPI() const
1151{
1152 return wxSize(100, 100);
1153}
1154
1155int wxWindowDC::GetDepth() const
c801d85f 1156{
b0e0d661
VZ
1157 wxFAIL_MSG(_T("not implemented"));
1158
1159 return -1;
903f689b 1160}
c801d85f 1161
d54e4256 1162#if wxUSE_SPLINES
c801d85f
KB
1163// ----------------------------------- spline code ----------------------------------------
1164
1165void wx_quadratic_spline(double a1, double b1, double a2, double b2,
1166 double a3, double b3, double a4, double b4);
4bc67cc5 1167void wx_clear_stack();
c801d85f
KB
1168int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
1169 double *y3, double *x4, double *y4);
1170void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
1171 double x4, double y4);
1172static bool wx_spline_add_point(double x, double y);
1173static void wx_spline_draw_point_array(wxDC *dc);
1174
1175wxList wx_spline_point_list;
1176
b0e0d661
VZ
1177#define half(z1, z2) ((z1+z2)/2.0)
1178#define THRESHOLD 5
c801d85f
KB
1179
1180/* iterative version */
1181
1182void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
1183 double b4)
1184{
1185 register double xmid, ymid;
1186 double x1, y1, x2, y2, x3, y3, x4, y4;
1187
1188 wx_clear_stack();
1189 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
1190
1191 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
1192 xmid = (double)half(x2, x3);
1193 ymid = (double)half(y2, y3);
b0e0d661
VZ
1194 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
1195 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
c801d85f
KB
1196 wx_spline_add_point( x1, y1 );
1197 wx_spline_add_point( xmid, ymid );
b0e0d661 1198 } else {
c801d85f
KB
1199 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
1200 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
1201 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
1202 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
b0e0d661 1203 }
c801d85f
KB
1204 }
1205}
1206
1207/* utilities used by spline drawing routines */
1208
1209typedef struct wx_spline_stack_struct {
1210 double x1, y1, x2, y2, x3, y3, x4, y4;
1211} Stack;
1212
1213#define SPLINE_STACK_DEPTH 20
1214static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
1215static Stack *wx_stack_top;
1216static int wx_stack_count;
1217
4bc67cc5 1218void wx_clear_stack()
c801d85f
KB
1219{
1220 wx_stack_top = wx_spline_stack;
1221 wx_stack_count = 0;
1222}
1223
1224void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
1225{
1226 wx_stack_top->x1 = x1;
1227 wx_stack_top->y1 = y1;
1228 wx_stack_top->x2 = x2;
1229 wx_stack_top->y2 = y2;
1230 wx_stack_top->x3 = x3;
1231 wx_stack_top->y3 = y3;
1232 wx_stack_top->x4 = x4;
1233 wx_stack_top->y4 = y4;
1234 wx_stack_top++;
1235 wx_stack_count++;
1236}
1237
1238int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
1239 double *x3, double *y3, double *x4, double *y4)
1240{
1241 if (wx_stack_count == 0)
b0e0d661 1242 return (0);
c801d85f
KB
1243 wx_stack_top--;
1244 wx_stack_count--;
1245 *x1 = wx_stack_top->x1;
1246 *y1 = wx_stack_top->y1;
1247 *x2 = wx_stack_top->x2;
1248 *y2 = wx_stack_top->y2;
1249 *x3 = wx_stack_top->x3;
1250 *y3 = wx_stack_top->y3;
1251 *x4 = wx_stack_top->x4;
1252 *y4 = wx_stack_top->y4;
1253 return (1);
1254}
1255
1256static bool wx_spline_add_point(double x, double y)
1257{
1258 wxPoint *point = new wxPoint ;
1259 point->x = (int) x;
1260 point->y = (int) y;
1261 wx_spline_point_list.Append((wxObject*)point);
1262 return TRUE;
1263}
1264
1265static void wx_spline_draw_point_array(wxDC *dc)
1266{
1267 dc->DrawLines(&wx_spline_point_list, 0, 0 );
1268 wxNode *node = wx_spline_point_list.First();
1269 while (node)
1270 {
1271 wxPoint *point = (wxPoint *)node->Data();
1272 delete point;
1273 delete node;
1274 node = wx_spline_point_list.First();
1275 }
1276}
1277
b0e0d661 1278void wxWindowDC::DoDrawSpline( wxList *points )
c801d85f 1279{
93c5dd39 1280 wxCHECK_RET( Ok(), _T("invalid window dc") );
4bc67cc5 1281
c801d85f
KB
1282 wxPoint *p;
1283 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
1284 double x1, y1, x2, y2;
1285
1286 wxNode *node = points->First();
1287 p = (wxPoint *)node->Data();
1288
1289 x1 = p->x;
1290 y1 = p->y;
1291
1292 node = node->Next();
1293 p = (wxPoint *)node->Data();
1294
1295 x2 = p->x;
1296 y2 = p->y;
1297 cx1 = (double)((x1 + x2) / 2);
1298 cy1 = (double)((y1 + y2) / 2);
1299 cx2 = (double)((cx1 + x2) / 2);
1300 cy2 = (double)((cy1 + y2) / 2);
1301
1302 wx_spline_add_point(x1, y1);
1303
1304 while ((node = node->Next()) != NULL)
1305 {
1306 p = (wxPoint *)node->Data();
b0e0d661
VZ
1307 x1 = x2;
1308 y1 = y2;
1309 x2 = p->x;
1310 y2 = p->y;
c801d85f
KB
1311 cx4 = (double)(x1 + x2) / 2;
1312 cy4 = (double)(y1 + y2) / 2;
1313 cx3 = (double)(x1 + cx4) / 2;
1314 cy3 = (double)(y1 + cy4) / 2;
1315
1316 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
1317
b0e0d661
VZ
1318 cx1 = cx4;
1319 cy1 = cy4;
c801d85f
KB
1320 cx2 = (double)(cx1 + x2) / 2;
1321 cy2 = (double)(cy1 + y2) / 2;
1322 }
1323
1324 wx_spline_add_point( cx1, cy1 );
1325 wx_spline_add_point( x2, y2 );
1326
1327 wx_spline_draw_point_array( this );
903f689b 1328}
ec758a20 1329
b0e0d661 1330#endif // wxUSE_SPLINE
ec758a20
RR
1331
1332//-----------------------------------------------------------------------------
1333// wxPaintDC
1334//-----------------------------------------------------------------------------
1335
1336IMPLEMENT_DYNAMIC_CLASS(wxPaintDC,wxWindowDC)
1337
4bc67cc5 1338wxPaintDC::wxPaintDC()
ec758a20
RR
1339 : wxWindowDC()
1340{
1341}
1342
1343wxPaintDC::wxPaintDC( wxWindow *win )
1344 : wxWindowDC( win )
1345{
1346}
1347
1348//-----------------------------------------------------------------------------
1349// wxClientDC
1350//-----------------------------------------------------------------------------
1351
1352IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC)
1353
4bc67cc5 1354wxClientDC::wxClientDC()
ec758a20
RR
1355 : wxWindowDC()
1356{
1357}
1358
1359wxClientDC::wxClientDC( wxWindow *win )
1360 : wxWindowDC( win )
1361{
1362}
1363