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