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