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