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