]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/dcclient.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "dcclient.h"
15 #define XCopyPlane XCOPYPLANE
18 #include "wx/dcclient.h"
19 #include "wx/dcmemory.h"
21 #include "wx/module.h"
24 #include "wx/gtk/win_gtk.h"
26 #include <math.h> // for floating-point functions
30 #include <gdk/gdkprivate.h>
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
37 #define USE_PAINT_REGION 1
39 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
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)
55 static GdkPixmap
*hatches
[num_hatches
];
56 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
58 extern GtkWidget
*wxGetRootWindow();
60 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
64 const double RAD2DEG
= 180.0 / M_PI
;
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
71 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
73 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
75 //-----------------------------------------------------------------------------
76 // temporary implementation of the missing GDK function
77 //-----------------------------------------------------------------------------
79 #include "gdk/gdkprivate.h"
81 void gdk_wx_draw_bitmap(GdkDrawable
*drawable
,
91 gint src_width
, src_height
;
93 GdkWindowPrivate
*drawable_private
;
94 GdkWindowPrivate
*src_private
;
95 GdkGCPrivate
*gc_private
;
98 g_return_if_fail (drawable
!= NULL
);
99 g_return_if_fail (src
!= NULL
);
100 g_return_if_fail (gc
!= NULL
);
103 if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
))
106 gdk_drawable_get_size(src
, &src_width
, &src_height
);
108 drawable_private
= (GdkWindowPrivate
*) drawable
;
109 src_private
= (GdkWindowPrivate
*) src
;
110 if (drawable_private
->destroyed
|| src_private
->destroyed
)
113 src_width
= src_private
->width
;
114 src_height
= src_private
->height
;
116 gc_private
= (GdkGCPrivate
*) gc
;
119 if (width
== -1) width
= src_width
;
120 if (height
== -1) height
= src_height
;
123 XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
),
125 GDK_WINDOW_XID(drawable
),
132 XCopyPlane( drawable_private
->xdisplay
,
133 src_private
->xwindow
,
134 drawable_private
->xwindow
,
143 //-----------------------------------------------------------------------------
144 // Implement Pool of Graphic contexts. Creating them takes too much time.
145 //-----------------------------------------------------------------------------
147 #define GC_POOL_SIZE 200
173 #define GC_POOL_ALLOC_SIZE 100
175 static int wxGCPoolSize
= 0;
177 static wxGC
*wxGCPool
= NULL
;
179 static void wxInitGCPool()
181 // This really could wait until the first call to
182 // wxGetPoolGC, but we will make the first allocation
183 // now when other initialization is being performed.
185 // Set initial pool size.
186 wxGCPoolSize
= GC_POOL_ALLOC_SIZE
;
188 // Allocate initial pool.
189 wxGCPool
= (wxGC
*)malloc(wxGCPoolSize
* sizeof(wxGC
));
190 if (wxGCPool
== NULL
)
192 // If we cannot malloc, then fail with error
193 // when debug is enabled. If debug is not enabled,
194 // the problem will eventually get caught
196 wxFAIL_MSG( wxT("Cannot allocate GC pool") );
200 // Zero initial pool.
201 memset(wxGCPool
, 0, wxGCPoolSize
* sizeof(wxGC
));
204 static void wxCleanUpGCPool()
206 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
208 if (wxGCPool
[i
].m_gc
)
209 gdk_gc_unref( wxGCPool
[i
].m_gc
);
217 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
221 // Look for an available GC.
222 for (int i
= 0; i
< wxGCPoolSize
; i
++)
224 if (!wxGCPool
[i
].m_gc
)
226 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
227 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
228 wxGCPool
[i
].m_type
= type
;
229 wxGCPool
[i
].m_used
= FALSE
;
231 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
233 wxGCPool
[i
].m_used
= TRUE
;
234 return wxGCPool
[i
].m_gc
;
238 // We did not find an available GC.
239 // We need to grow the GC pool.
240 pptr
= (wxGC
*)realloc(wxGCPool
,
241 (wxGCPoolSize
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
));
244 // Initialize newly allocated pool.
246 memset(&wxGCPool
[wxGCPoolSize
], 0,
247 GC_POOL_ALLOC_SIZE
*sizeof(wxGC
));
249 // Initialize entry we will return.
250 wxGCPool
[wxGCPoolSize
].m_gc
= gdk_gc_new( window
);
251 gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE
);
252 wxGCPool
[wxGCPoolSize
].m_type
= type
;
253 wxGCPool
[wxGCPoolSize
].m_used
= TRUE
;
255 // Set new value of pool size.
256 wxGCPoolSize
+= GC_POOL_ALLOC_SIZE
;
258 // Return newly allocated entry.
259 return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
;
262 // The realloc failed. Fall through to error.
263 wxFAIL_MSG( wxT("No GC available") );
265 return (GdkGC
*) NULL
;
268 static void wxFreePoolGC( GdkGC
*gc
)
270 for (int i
= 0; i
< wxGCPoolSize
; i
++)
272 if (wxGCPool
[i
].m_gc
== gc
)
274 wxGCPool
[i
].m_used
= FALSE
;
279 wxFAIL_MSG( wxT("Wrong GC") );
282 //-----------------------------------------------------------------------------
284 //-----------------------------------------------------------------------------
286 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
288 wxWindowDC::wxWindowDC()
290 m_penGC
= (GdkGC
*) NULL
;
291 m_brushGC
= (GdkGC
*) NULL
;
292 m_textGC
= (GdkGC
*) NULL
;
293 m_bgGC
= (GdkGC
*) NULL
;
294 m_cmap
= (GdkColormap
*) NULL
;
296 m_isScreenDC
= FALSE
;
297 m_owner
= (wxWindow
*)NULL
;
299 m_context
= (PangoContext
*)NULL
;
300 m_fontdesc
= (PangoFontDescription
*)NULL
;
304 wxWindowDC::wxWindowDC( wxWindow
*window
)
306 wxASSERT_MSG( window
, wxT("DC needs a window") );
308 m_penGC
= (GdkGC
*) NULL
;
309 m_brushGC
= (GdkGC
*) NULL
;
310 m_textGC
= (GdkGC
*) NULL
;
311 m_bgGC
= (GdkGC
*) NULL
;
312 m_cmap
= (GdkColormap
*) NULL
;
313 m_owner
= (wxWindow
*)NULL
;
315 m_isScreenDC
= FALSE
;
316 m_font
= window
->GetFont();
318 GtkWidget
*widget
= window
->m_wxwindow
;
320 // some controls don't have m_wxwindow - like wxStaticBox, but the user
321 // code should still be able to create wxClientDCs for them, so we will
322 // use the parent window here then
325 window
= window
->GetParent();
326 widget
= window
->m_wxwindow
;
329 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
332 m_context
= gtk_widget_get_pango_context( widget
);
333 m_fontdesc
= widget
->style
->font_desc
;
336 GtkPizza
*pizza
= GTK_PIZZA( widget
);
337 m_window
= pizza
->bin_window
;
342 /* don't report problems */
348 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
352 /* this must be done after SetUpDC, bacause SetUpDC calls the
353 repective SetBrush, SetPen, SetBackground etc functions
354 to set up the DC. SetBackground call m_owner->SetBackground
355 and this might not be desired as the standard dc background
356 is white whereas a window might assume gray to be the
357 standard (as e.g. wxStatusBar) */
362 wxWindowDC::~wxWindowDC()
367 void wxWindowDC::SetUpDC()
371 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
375 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
376 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
377 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
378 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
381 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
383 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
384 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
385 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
386 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
390 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
391 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
392 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
393 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
396 /* background colour */
397 m_backgroundBrush
= *wxWHITE_BRUSH
;
398 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
399 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
402 m_textForegroundColour
.CalcPixel( m_cmap
);
403 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
405 m_textBackgroundColour
.CalcPixel( m_cmap
);
406 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
408 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
411 m_pen
.GetColour().CalcPixel( m_cmap
);
412 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
413 gdk_gc_set_background( m_penGC
, bg_col
);
415 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
418 m_brush
.GetColour().CalcPixel( m_cmap
);
419 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
420 gdk_gc_set_background( m_brushGC
, bg_col
);
422 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
425 gdk_gc_set_background( m_bgGC
, bg_col
);
426 gdk_gc_set_foreground( m_bgGC
, bg_col
);
428 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
431 gdk_gc_set_function( m_textGC
, GDK_COPY
);
432 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
433 gdk_gc_set_function( m_penGC
, GDK_COPY
);
436 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
437 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
438 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
439 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
443 hatch_bitmap
= hatches
;
444 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
445 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
446 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
447 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
448 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
449 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
453 void wxWindowDC::DoGetSize( int* width
, int* height
) const
455 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
457 m_owner
->GetSize(width
, height
);
460 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
461 const wxColour
& col
, int style
);
463 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
464 const wxColour
& col
, int style
)
466 return wxDoFloodFill(this, x
, y
, col
, style
);
469 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
471 // Generic (and therefore rather inefficient) method.
472 // Could be improved.
474 wxBitmap
bitmap(1, 1);
475 memdc
.SelectObject(bitmap
);
476 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
477 memdc
.SelectObject(wxNullBitmap
);
479 wxImage image
= bitmap
.ConvertToImage();
480 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
484 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
486 wxCHECK_RET( Ok(), wxT("invalid window dc") );
488 if (m_pen
.GetStyle() != wxTRANSPARENT
)
491 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
493 CalcBoundingBox(x1
, y1
);
494 CalcBoundingBox(x2
, y2
);
498 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
500 wxCHECK_RET( Ok(), wxT("invalid window dc") );
502 if (m_pen
.GetStyle() != wxTRANSPARENT
)
507 wxCoord xx
= XLOG2DEV(x
);
508 wxCoord yy
= YLOG2DEV(y
);
511 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
512 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
517 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
518 wxCoord xc
, wxCoord yc
)
520 wxCHECK_RET( Ok(), wxT("invalid window dc") );
522 wxCoord xx1
= XLOG2DEV(x1
);
523 wxCoord yy1
= YLOG2DEV(y1
);
524 wxCoord xx2
= XLOG2DEV(x2
);
525 wxCoord yy2
= YLOG2DEV(y2
);
526 wxCoord xxc
= XLOG2DEV(xc
);
527 wxCoord yyc
= YLOG2DEV(yc
);
528 double dx
= xx1
- xxc
;
529 double dy
= yy1
- yyc
;
530 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
531 wxCoord r
= (wxCoord
)radius
;
532 double radius1
, radius2
;
534 if (xx1
== xx2
&& yy1
== yy2
)
542 radius1
= radius2
= 0.0;
546 radius1
= (xx1
- xxc
== 0) ?
547 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
548 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
549 radius2
= (xx2
- xxc
== 0) ?
550 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
551 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
553 wxCoord alpha1
= wxCoord(radius1
* 64.0);
554 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
555 while (alpha2
<= 0) alpha2
+= 360*64;
556 while (alpha1
> 360*64) alpha1
-= 360*64;
560 if (m_brush
.GetStyle() != wxTRANSPARENT
)
562 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
564 gdk_gc_set_ts_origin( m_textGC
,
565 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
566 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
567 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
568 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
570 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
572 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
573 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
574 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
576 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
578 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
579 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
580 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
582 if (m_brush
.GetStyle() == wxSTIPPLE
)
584 gdk_gc_set_ts_origin( m_brushGC
,
585 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
586 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
587 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
588 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
592 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
596 if (m_pen
.GetStyle() != wxTRANSPARENT
)
598 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
600 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
601 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
605 CalcBoundingBox (x1
, y1
);
606 CalcBoundingBox (x2
, y2
);
609 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
611 wxCHECK_RET( Ok(), wxT("invalid window dc") );
613 wxCoord xx
= XLOG2DEV(x
);
614 wxCoord yy
= YLOG2DEV(y
);
615 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
616 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
618 // CMB: handle -ve width and/or height
619 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
620 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
624 wxCoord start
= wxCoord(sa
* 64.0);
625 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
627 if (m_brush
.GetStyle() != wxTRANSPARENT
)
629 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
631 gdk_gc_set_ts_origin( m_textGC
,
632 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
633 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
634 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
635 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
637 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
639 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
640 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
641 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
643 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
645 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
646 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
647 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
649 if (m_brush
.GetStyle() == wxSTIPPLE
)
651 gdk_gc_set_ts_origin( m_brushGC
,
652 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
653 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
654 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
655 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
659 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
663 if (m_pen
.GetStyle() != wxTRANSPARENT
)
664 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
667 CalcBoundingBox (x
, y
);
668 CalcBoundingBox (x
+ width
, y
+ height
);
671 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
673 wxCHECK_RET( Ok(), wxT("invalid window dc") );
675 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
676 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
678 CalcBoundingBox (x
, y
);
681 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
683 wxCHECK_RET( Ok(), wxT("invalid window dc") );
685 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
688 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
690 for (int i
= 0; i
< n
-1; i
++)
692 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
693 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
694 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
695 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
698 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
700 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
704 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
706 wxCHECK_RET( Ok(), wxT("invalid window dc") );
710 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
712 for (i
= 0 ; i
< n
; i
++)
714 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
715 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
717 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
722 if (m_brush
.GetStyle() != wxTRANSPARENT
)
724 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
726 gdk_gc_set_ts_origin( m_textGC
,
727 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
728 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
729 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
730 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
732 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
734 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
735 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
736 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
738 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
740 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
741 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
742 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
744 if (m_brush
.GetStyle() == wxSTIPPLE
)
746 gdk_gc_set_ts_origin( m_brushGC
,
747 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
748 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
749 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
750 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
754 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
758 if (m_pen
.GetStyle() != wxTRANSPARENT
)
760 for (i
= 0 ; i
< n
; i
++)
762 gdk_draw_line( m_window
, m_penGC
,
765 gdkpoints
[(i
+1)%n
].x
,
766 gdkpoints
[(i
+1)%n
].y
);
774 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
776 wxCHECK_RET( Ok(), wxT("invalid window dc") );
778 wxCoord xx
= XLOG2DEV(x
);
779 wxCoord yy
= YLOG2DEV(y
);
780 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
781 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
783 // CMB: draw nothing if transformed w or h is 0
784 if (ww
== 0 || hh
== 0) return;
786 // CMB: handle -ve width and/or height
787 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
788 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
792 if (m_brush
.GetStyle() != wxTRANSPARENT
)
794 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
796 gdk_gc_set_ts_origin( m_textGC
,
797 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
798 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
799 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
800 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
802 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
804 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
805 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
806 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
808 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
810 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
811 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
812 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
814 if (m_brush
.GetStyle() == wxSTIPPLE
)
816 gdk_gc_set_ts_origin( m_brushGC
,
817 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
818 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
819 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
820 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
824 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
828 if (m_pen
.GetStyle() != wxTRANSPARENT
)
829 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
832 CalcBoundingBox( x
, y
);
833 CalcBoundingBox( x
+ width
, y
+ height
);
836 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
838 wxCHECK_RET( Ok(), wxT("invalid window dc") );
840 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
842 wxCoord xx
= XLOG2DEV(x
);
843 wxCoord yy
= YLOG2DEV(y
);
844 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
845 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
846 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
848 // CMB: handle -ve width and/or height
849 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
850 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
852 // CMB: if radius is zero use DrawRectangle() instead to avoid
853 // X drawing errors with small radii
856 DrawRectangle( x
, y
, width
, height
);
860 // CMB: draw nothing if transformed w or h is 0
861 if (ww
== 0 || hh
== 0) return;
863 // CMB: adjust size if outline is drawn otherwise the result is
864 // 1 pixel too wide and high
865 if (m_pen
.GetStyle() != wxTRANSPARENT
)
873 // CMB: ensure dd is not larger than rectangle otherwise we
874 // get an hour glass shape
876 if (dd
> ww
) dd
= ww
;
877 if (dd
> hh
) dd
= hh
;
880 if (m_brush
.GetStyle() != wxTRANSPARENT
)
882 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
884 gdk_gc_set_ts_origin( m_textGC
,
885 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
886 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
887 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
888 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
889 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
890 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
891 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
892 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
893 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
895 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
897 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
898 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
899 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
900 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
901 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
902 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
903 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
904 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
906 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
908 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
909 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
910 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
911 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
912 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
913 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
914 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
915 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
917 if (m_brush
.GetStyle() == wxSTIPPLE
)
919 gdk_gc_set_ts_origin( m_brushGC
,
920 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
921 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
922 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
923 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
924 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
925 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
926 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
927 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
928 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
932 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
933 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
934 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
935 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
936 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
937 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
941 if (m_pen
.GetStyle() != wxTRANSPARENT
)
943 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
944 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
945 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
946 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
947 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
948 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
949 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
950 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
954 // this ignores the radius
955 CalcBoundingBox( x
, y
);
956 CalcBoundingBox( x
+ width
, y
+ height
);
959 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
961 wxCHECK_RET( Ok(), wxT("invalid window dc") );
963 wxCoord xx
= XLOG2DEV(x
);
964 wxCoord yy
= YLOG2DEV(y
);
965 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
966 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
968 // CMB: handle -ve width and/or height
969 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
970 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
974 if (m_brush
.GetStyle() != wxTRANSPARENT
)
976 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
978 gdk_gc_set_ts_origin( m_textGC
,
979 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
980 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
981 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
982 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
984 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
986 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
987 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
988 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
990 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
992 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
993 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
994 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
996 if (m_brush
.GetStyle() == wxSTIPPLE
)
998 gdk_gc_set_ts_origin( m_brushGC
,
999 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1000 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1001 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1002 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1006 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1010 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1011 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1014 CalcBoundingBox( x
, y
);
1015 CalcBoundingBox( x
+ width
, y
+ height
);
1018 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1020 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1021 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1024 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1025 wxCoord x
, wxCoord y
,
1028 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1030 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1032 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1034 /* scale/translate size and position */
1035 int xx
= XLOG2DEV(x
);
1036 int yy
= YLOG2DEV(y
);
1038 int w
= bitmap
.GetWidth();
1039 int h
= bitmap
.GetHeight();
1041 CalcBoundingBox( x
, y
);
1042 CalcBoundingBox( x
+ w
, y
+ h
);
1044 if (!m_window
) return;
1046 int ww
= XLOG2DEVREL(w
);
1047 int hh
= YLOG2DEVREL(h
);
1049 /* compare to current clipping region */
1050 if (!m_currentClippingRegion
.IsNull())
1052 wxRegion
tmp( xx
,yy
,ww
,hh
);
1053 tmp
.Intersect( m_currentClippingRegion
);
1058 /* scale bitmap if required */
1059 wxBitmap use_bitmap
;
1060 if ((w
!= ww
) || (h
!= hh
))
1062 wxImage image
= bitmap
.ConvertToImage();
1063 image
.Rescale( ww
, hh
);
1065 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1067 use_bitmap
= wxBitmap(image
);
1071 use_bitmap
= bitmap
;
1074 /* apply mask if any */
1075 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1076 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1078 if (useMask
&& mask
)
1080 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1081 #ifndef __WXGTK20__ // TODO fix crash
1082 if (!m_currentClippingRegion
.IsNull())
1085 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1086 GdkGC
*gc
= gdk_gc_new( new_mask
);
1088 gdk_gc_set_foreground( gc
, &col
);
1089 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1091 gdk_gc_set_background( gc
, &col
);
1093 gdk_gc_set_foreground( gc
, &col
);
1094 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1095 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1096 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1097 gdk_gc_set_stipple( gc
, mask
);
1098 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1105 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1107 gdk_gc_set_clip_mask( m_textGC
, mask
);
1108 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1113 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1115 gdk_gc_set_clip_mask( m_penGC
, mask
);
1116 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1120 gdk_bitmap_unref( new_mask
);
1123 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1124 drawing a mono-bitmap (XBitmap) we use the current text GC */
1126 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1128 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1130 /* remove mask again if any */
1131 if (useMask
&& mask
)
1135 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1136 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1137 if (!m_currentClippingRegion
.IsNull())
1138 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1142 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1143 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1144 if (!m_currentClippingRegion
.IsNull())
1145 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1150 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1151 wxCoord width
, wxCoord height
,
1153 wxCoord xsrc
, wxCoord ysrc
,
1156 wxCoord xsrcMask
, wxCoord ysrcMask
)
1158 /* this is the nth try to get this utterly useless function to
1159 work. it now completely ignores the scaling or translation
1160 of the source dc, but scales correctly on the target dc and
1161 knows about possible mask information in a memory dc. */
1163 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1165 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1167 if (!m_window
) return FALSE
;
1170 // transform the source DC coords to the device ones
1171 xsrc
= source
->XLOG2DEV(xsrc
);
1172 ysrc
= source
->YLOG2DEV(ysrc
);
1175 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1176 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1178 bool use_bitmap_method
= FALSE
;
1179 bool is_mono
= FALSE
;
1181 /* TODO: use the mask origin when drawing transparently */
1182 if (xsrcMask
== -1 && ysrcMask
== -1)
1184 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1187 if (srcDC
->m_isMemDC
)
1189 if (!memDC
->m_selected
.Ok()) return FALSE
;
1191 /* we use the "XCopyArea" way to copy a memory dc into
1192 y different window if the memory dc BOTH
1193 a) doesn't have any mask or its mask isn't used
1197 if (useMask
&& (memDC
->m_selected
.GetMask()))
1199 /* we HAVE TO use the direct way for memory dcs
1200 that have mask since the XCopyArea doesn't know
1202 use_bitmap_method
= TRUE
;
1204 else if (memDC
->m_selected
.GetDepth() == 1)
1206 /* we HAVE TO use the direct way for memory dcs
1207 that are bitmaps because XCopyArea doesn't cope
1208 with different bit depths */
1210 use_bitmap_method
= TRUE
;
1212 else if ((xsrc
== 0) && (ysrc
== 0) &&
1213 (width
== memDC
->m_selected
.GetWidth()) &&
1214 (height
== memDC
->m_selected
.GetHeight()))
1216 /* we SHOULD use the direct way if all of the bitmap
1217 in the memory dc is copied in which case XCopyArea
1218 wouldn't be able able to boost performace by reducing
1219 the area to be scaled */
1220 use_bitmap_method
= TRUE
;
1224 use_bitmap_method
= FALSE
;
1228 CalcBoundingBox( xdest
, ydest
);
1229 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1231 /* scale/translate size and position */
1232 wxCoord xx
= XLOG2DEV(xdest
);
1233 wxCoord yy
= YLOG2DEV(ydest
);
1235 wxCoord ww
= XLOG2DEVREL(width
);
1236 wxCoord hh
= YLOG2DEVREL(height
);
1238 /* compare to current clipping region */
1239 if (!m_currentClippingRegion
.IsNull())
1241 wxRegion
tmp( xx
,yy
,ww
,hh
);
1242 tmp
.Intersect( m_currentClippingRegion
);
1247 int old_logical_func
= m_logicalFunction
;
1248 SetLogicalFunction( logical_func
);
1250 if (use_bitmap_method
)
1252 /* scale/translate bitmap size */
1253 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1254 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1256 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1257 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1259 /* scale bitmap if required */
1260 wxBitmap use_bitmap
;
1262 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1264 wxImage image
= memDC
->m_selected
.ConvertToImage();
1265 image
= image
.Scale( bm_ww
, bm_hh
);
1268 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1270 use_bitmap
= wxBitmap(image
);
1274 use_bitmap
= memDC
->m_selected
;
1277 /* apply mask if any */
1278 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1279 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1281 if (useMask
&& mask
)
1283 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1284 #ifndef __WXGTK20__ // TODO fix crash
1285 if (!m_currentClippingRegion
.IsNull())
1288 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1289 GdkGC
*gc
= gdk_gc_new( new_mask
);
1291 gdk_gc_set_foreground( gc
, &col
);
1292 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1294 gdk_gc_set_background( gc
, &col
);
1296 gdk_gc_set_foreground( gc
, &col
);
1297 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1298 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1299 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1300 gdk_gc_set_stipple( gc
, mask
);
1301 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1308 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1310 gdk_gc_set_clip_mask( m_textGC
, mask
);
1311 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1316 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1318 gdk_gc_set_clip_mask( m_penGC
, mask
);
1319 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1322 gdk_bitmap_unref( new_mask
);
1325 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1326 drawing a mono-bitmap (XBitmap) we use the current text GC */
1329 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1331 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1333 /* remove mask again if any */
1334 if (useMask
&& mask
)
1338 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1339 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1340 if (!m_currentClippingRegion
.IsNull())
1341 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1345 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1346 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1347 if (!m_currentClippingRegion
.IsNull())
1348 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1352 else /* use_bitmap_method */
1354 if ((width
!= ww
) || (height
!= hh
))
1356 /* draw source window into a bitmap as we cannot scale
1357 a window in contrast to a bitmap. this would actually
1358 work with memory dcs as well, but we'd lose the mask
1359 information and waste one step in this process since
1360 a memory already has a bitmap. all this is slightly
1361 inefficient as we could take an XImage directly from
1362 an X window, but we'd then also have to care that
1363 the window is not outside the screen (in which case
1364 we'd get a BadMatch or what not).
1365 Is a double XGetImage and combined XGetPixel and
1366 XPutPixel really faster? I'm not sure. look at wxXt
1367 for a different implementation of the same problem. */
1369 wxBitmap
bitmap( width
, height
);
1371 /* copy including child window contents */
1372 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1373 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1375 xsrc
, ysrc
, width
, height
);
1376 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1379 wxImage image
= bitmap
.ConvertToImage();
1380 image
= image
.Scale( ww
, hh
);
1382 /* convert to bitmap */
1383 bitmap
= wxBitmap(image
);
1385 /* draw scaled bitmap */
1386 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1391 /* No scaling and not a memory dc with a mask either */
1393 /* copy including child window contents */
1394 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1395 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1397 xsrc
, ysrc
, width
, height
);
1398 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1402 SetLogicalFunction( old_logical_func
);
1406 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1408 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1410 if (!m_window
) return;
1412 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1414 wxCHECK_RET( font
, wxT("invalid font") );
1416 #if defined(__WXGTK20__)
1417 wxCHECK_RET( m_context
, wxT("no Pango context") );
1423 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1424 // TODO: the layout engine should be abstracted at a higher level!
1425 PangoLayout
*layout
= pango_layout_new(m_context
);
1426 pango_layout_set_font_description(layout
, m_fontdesc
);
1428 const wxWX2MBbuf data
= text
.mb_str(wxConvUTF8
);
1429 pango_layout_set_text(layout
, data
, strlen(data
));
1431 PangoLayoutLine
*line
= (PangoLayoutLine
*)pango_layout_get_lines(layout
)->data
;
1432 PangoRectangle rect
;
1433 pango_layout_line_get_extents(line
, NULL
, &rect
);
1434 wxCoord width
= rect
.width
;
1435 wxCoord height
= rect
.height
;
1436 gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout
);
1438 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1439 wxCoord height
= font
->ascent
+ font
->descent
;
1441 if ( m_backgroundMode
== wxSOLID
)
1443 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1444 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1445 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1447 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1448 #endif // GTK+ 2.0/1.x
1450 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1451 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1452 properties (see wxXt implementation) */
1453 if (m_font
.GetUnderlined())
1455 wxCoord ul_y
= y
+ font
->ascent
;
1456 if (font
->descent
> 0) ul_y
++;
1457 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1460 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1461 g_object_unref( G_OBJECT( layout
) );
1464 width
= wxCoord(width
/ m_scaleX
);
1465 height
= wxCoord(height
/ m_scaleY
);
1466 CalcBoundingBox (x
+ width
, y
+ height
);
1467 CalcBoundingBox (x
, y
);
1470 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1474 DrawText(text
, x
, y
);
1478 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1480 if (!m_window
) return;
1482 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1484 wxCHECK_RET( font
, wxT("invalid font") );
1486 // the size of the text
1487 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1488 wxCoord h
= font
->ascent
+ font
->descent
;
1490 // draw the string normally
1493 dc
.SelectObject(src
);
1494 dc
.SetFont(GetFont());
1495 dc
.SetBackground(*wxWHITE_BRUSH
);
1496 dc
.SetBrush(*wxBLACK_BRUSH
);
1498 dc
.DrawText(text
, 0, 0);
1499 dc
.SelectObject(wxNullBitmap
);
1501 // Calculate the size of the rotated bounding box.
1502 double rad
= DegToRad(angle
);
1503 double dx
= cos(rad
),
1506 // the rectngle vertices are counted clockwise with the first one being at
1507 // (0, 0) (or, rather, at (x, y))
1509 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1512 double x3
= x4
+ x2
,
1516 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1517 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1518 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1519 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1521 // prepare to blit-with-rotate the bitmap to the DC
1522 wxImage image
= src
.ConvertToImage();
1524 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1525 *colBack
= m_textBackgroundColour
.GetColor();
1527 bool textColSet
= TRUE
;
1529 unsigned char *data
= image
.GetData();
1531 // paint pixel by pixel
1532 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1534 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1536 // transform source coords to dest coords
1537 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1538 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1539 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1540 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1543 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1544 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1546 // change colour if needed
1547 if ( textPixel
!= textColSet
)
1549 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1552 textColSet
= textPixel
;
1555 // don't use DrawPoint() because it uses the current pen
1556 // colour, and we don't need it here
1557 gdk_draw_point( m_window
, m_textGC
,
1558 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
1563 // it would be better to draw with non underlined font and draw the line
1564 // manually here (it would be more straight...)
1566 if ( m_font
.GetUnderlined() )
1568 gdk_draw_line( m_window
, m_textGC
,
1569 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1570 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1574 // restore the font colour
1575 gdk_gc_set_foreground( m_textGC
, colText
);
1577 // update the bounding box
1578 CalcBoundingBox(x
+ minX
, y
+ minY
);
1579 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1582 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1583 wxCoord
*width
, wxCoord
*height
,
1584 wxCoord
*descent
, wxCoord
*externalLeading
,
1585 wxFont
*theFont
) const
1587 wxFont fontToUse
= m_font
;
1588 if (theFont
) fontToUse
= *theFont
;
1590 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1591 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1592 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1593 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1594 if (externalLeading
) (*externalLeading
) = 0; // ??
1597 wxCoord
wxWindowDC::GetCharWidth() const
1599 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1600 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1602 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1605 wxCoord
wxWindowDC::GetCharHeight() const
1607 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1608 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1610 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1613 void wxWindowDC::Clear()
1615 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1617 if (!m_window
) return;
1619 // VZ: the code below results in infinite recursion and crashes when
1620 // dc.Clear() is done from OnPaint() so I disable it for now.
1621 // I don't know what the correct fix is but Clear() surely should not
1622 // reenter OnPaint()!
1624 /* - we either are a memory dc or have a window as the
1625 owner. anything else shouldn't happen.
1626 - we don't use gdk_window_clear() as we don't set
1627 the window's background colour anymore. it is too
1628 much pain to keep the DC's and the window's back-
1629 ground colour in synch. */
1640 GetSize( &width
, &height
);
1641 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1646 GetSize( &width
, &height
);
1647 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1651 void wxWindowDC::SetFont( const wxFont
&font
)
1653 // It is common practice to set the font to wxNullFont, so
1654 // don't consider it to be an error
1655 // wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") );
1663 void wxWindowDC::SetPen( const wxPen
&pen
)
1665 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1667 if (m_pen
== pen
) return;
1671 if (!m_pen
.Ok()) return;
1673 if (!m_window
) return;
1675 gint width
= m_pen
.GetWidth();
1678 // CMB: if width is non-zero scale it with the dc
1683 // X doesn't allow different width in x and y and so we take
1686 ( fabs((double) XLOG2DEVREL(width
)) +
1687 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1691 static const wxGTKDash dotted
[] = {1, 1};
1692 static const wxGTKDash short_dashed
[] = {2, 2};
1693 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1694 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1696 // We express dash pattern in pen width unit, so we are
1697 // independent of zoom factor and so on...
1699 const wxGTKDash
*req_dash
;
1701 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1702 switch (m_pen
.GetStyle())
1706 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1707 req_nb_dash
= m_pen
.GetDashCount();
1708 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1713 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1720 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1722 req_dash
= wxCoord_dashed
;
1727 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1729 req_dash
= short_dashed
;
1734 // lineStyle = GDK_LINE_DOUBLE_DASH;
1735 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1737 req_dash
= dotted_dashed
;
1742 case wxSTIPPLE_MASK_OPAQUE
:
1747 lineStyle
= GDK_LINE_SOLID
;
1748 req_dash
= (wxGTKDash
*)NULL
;
1754 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1755 if (req_dash
&& req_nb_dash
)
1757 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1760 for (int i
= 0; i
< req_nb_dash
; i
++)
1761 real_req_dash
[i
] = req_dash
[i
] * width
;
1762 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1763 delete[] real_req_dash
;
1767 // No Memory. We use non-scaled dash pattern...
1768 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1773 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1774 switch (m_pen
.GetCap())
1776 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1777 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1784 capStyle
= GDK_CAP_NOT_LAST
;
1788 capStyle
= GDK_CAP_ROUND
;
1794 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1795 switch (m_pen
.GetJoin())
1797 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1798 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1800 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1803 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1805 m_pen
.GetColour().CalcPixel( m_cmap
);
1806 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1809 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1811 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1813 if (m_brush
== brush
) return;
1817 if (!m_brush
.Ok()) return;
1819 if (!m_window
) return;
1821 m_brush
.GetColour().CalcPixel( m_cmap
);
1822 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1824 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1826 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1828 if (m_brush
.GetStipple()->GetPixmap())
1830 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1831 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1835 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1836 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1840 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1842 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1843 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1846 if (IS_HATCH(m_brush
.GetStyle()))
1848 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1849 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1850 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1854 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1856 /* CMB 21/7/98: Added SetBackground. Sets background brush
1857 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1859 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1861 if (m_backgroundBrush
== brush
) return;
1863 m_backgroundBrush
= brush
;
1865 if (!m_backgroundBrush
.Ok()) return;
1867 if (!m_window
) return;
1869 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1870 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1871 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1872 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1873 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1875 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1877 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1879 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1881 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1882 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1886 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1887 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1891 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1893 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1894 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1895 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1899 void wxWindowDC::SetLogicalFunction( int function
)
1901 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1903 if (m_logicalFunction
== function
)
1906 // VZ: shouldn't this be a CHECK?
1910 GdkFunction mode
= GDK_COPY
;
1913 case wxXOR
: mode
= GDK_XOR
; break;
1914 case wxINVERT
: mode
= GDK_INVERT
; break;
1915 #if (GTK_MINOR_VERSION > 0)
1916 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1917 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1918 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1919 case wxSET
: mode
= GDK_SET
; break;
1920 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1921 case wxAND
: mode
= GDK_AND
; break;
1922 case wxOR
: mode
= GDK_OR
; break;
1923 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1924 case wxNAND
: mode
= GDK_NAND
; break;
1925 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1926 case wxCOPY
: mode
= GDK_COPY
; break;
1927 case wxNO_OP
: mode
= GDK_NOOP
; break;
1928 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1930 // unsupported by GTK
1931 case wxNOR
: mode
= GDK_COPY
; break;
1935 wxFAIL_MSG( wxT("unsupported logical function") );
1940 m_logicalFunction
= function
;
1942 gdk_gc_set_function( m_penGC
, mode
);
1943 gdk_gc_set_function( m_brushGC
, mode
);
1945 // to stay compatible with wxMSW, we don't apply ROPs to the text
1946 // operations (i.e. DrawText/DrawRotatedText).
1947 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1948 gdk_gc_set_function( m_textGC
, mode
);
1951 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1953 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1955 // don't set m_textForegroundColour to an invalid colour as we'd crash
1956 // later then (we use m_textForegroundColour.GetColor() without checking
1958 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1961 m_textForegroundColour
= col
;
1965 m_textForegroundColour
.CalcPixel( m_cmap
);
1966 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1970 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1972 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1975 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1978 m_textBackgroundColour
= col
;
1982 m_textBackgroundColour
.CalcPixel( m_cmap
);
1983 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1987 void wxWindowDC::SetBackgroundMode( int mode
)
1989 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1991 m_backgroundMode
= mode
;
1993 if (!m_window
) return;
1995 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1996 // transparent/solid background mode
1998 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2000 gdk_gc_set_fill( m_brushGC
,
2001 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2005 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2007 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2010 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2012 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2014 if (!m_window
) return;
2017 rect
.x
= XLOG2DEV(x
);
2018 rect
.y
= YLOG2DEV(y
);
2019 rect
.width
= XLOG2DEVREL(width
);
2020 rect
.height
= YLOG2DEVREL(height
);
2022 if (!m_currentClippingRegion
.IsNull())
2023 m_currentClippingRegion
.Intersect( rect
);
2025 m_currentClippingRegion
.Union( rect
);
2027 #if USE_PAINT_REGION
2028 if (!m_paintClippingRegion
.IsNull())
2029 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2032 wxCoord xx
, yy
, ww
, hh
;
2033 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2034 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2036 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2037 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2038 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2039 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2042 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2044 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2048 DestroyClippingRegion();
2052 if (!m_window
) return;
2054 if (!m_currentClippingRegion
.IsNull())
2055 m_currentClippingRegion
.Intersect( region
);
2057 m_currentClippingRegion
.Union( region
);
2059 #if USE_PAINT_REGION
2060 if (!m_paintClippingRegion
.IsNull())
2061 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2064 wxCoord xx
, yy
, ww
, hh
;
2065 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2066 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2068 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2069 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2070 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2071 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2074 void wxWindowDC::DestroyClippingRegion()
2076 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2078 wxDC::DestroyClippingRegion();
2080 m_currentClippingRegion
.Clear();
2082 #if USE_PAINT_REGION
2083 if (!m_paintClippingRegion
.IsEmpty())
2084 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2087 if (!m_window
) return;
2089 if (m_currentClippingRegion
.IsEmpty())
2091 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2092 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2093 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2094 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2098 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2099 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2100 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2101 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2105 void wxWindowDC::Destroy()
2107 if (m_penGC
) wxFreePoolGC( m_penGC
);
2108 m_penGC
= (GdkGC
*) NULL
;
2109 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2110 m_brushGC
= (GdkGC
*) NULL
;
2111 if (m_textGC
) wxFreePoolGC( m_textGC
);
2112 m_textGC
= (GdkGC
*) NULL
;
2113 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2114 m_bgGC
= (GdkGC
*) NULL
;
2117 void wxWindowDC::ComputeScaleAndOrigin()
2119 /* CMB: copy scale to see if it changes */
2120 double origScaleX
= m_scaleX
;
2121 double origScaleY
= m_scaleY
;
2123 wxDC::ComputeScaleAndOrigin();
2125 /* CMB: if scale has changed call SetPen to recalulate the line width */
2126 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2129 /* this is a bit artificial, but we need to force wxDC to think
2130 the pen has changed */
2137 // Resolution in pixels per logical inch
2138 wxSize
wxWindowDC::GetPPI() const
2140 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2143 int wxWindowDC::GetDepth() const
2145 wxFAIL_MSG(wxT("not implemented"));
2151 //-----------------------------------------------------------------------------
2153 //-----------------------------------------------------------------------------
2155 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2157 wxPaintDC::wxPaintDC( wxWindow
*win
)
2160 #if USE_PAINT_REGION
2161 if (!win
->m_clipPaintRegion
)
2164 m_paintClippingRegion
= win
->GetUpdateRegion();
2165 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2168 m_paintClippingRegion
= win
->GetUpdateRegion();
2169 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2172 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2174 gdk_gc_set_clip_region( m_penGC
, region
);
2175 gdk_gc_set_clip_region( m_brushGC
, region
);
2176 gdk_gc_set_clip_region( m_textGC
, region
);
2177 gdk_gc_set_clip_region( m_bgGC
, region
);
2180 #endif // USE_PAINT_REGION
2183 //-----------------------------------------------------------------------------
2185 //-----------------------------------------------------------------------------
2187 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2189 wxClientDC::wxClientDC( wxWindow
*win
)
2192 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2194 #ifdef __WXUNIVERSAL__
2195 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2196 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2197 wxSize size
= win
->GetClientSize();
2198 SetClippingRegion(wxPoint(0, 0), size
);
2199 #endif // __WXUNIVERSAL__
2202 void wxClientDC::DoGetSize(int *width
, int *height
) const
2204 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2206 m_owner
->GetClientSize( width
, height
);
2209 // ----------------------------------------------------------------------------
2211 // ----------------------------------------------------------------------------
2213 class wxDCModule
: public wxModule
2220 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2223 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2225 bool wxDCModule::OnInit()
2231 void wxDCModule::OnExit()