]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk1/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"
23 #include "wx/fontutil.h"
25 #include "wx/gtk/win_gtk.h"
27 #include <math.h> // for floating-point functions
31 #include <gdk/gdkprivate.h>
34 //-----------------------------------------------------------------------------
36 //-----------------------------------------------------------------------------
38 #define USE_PAINT_REGION 1
40 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
52 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
53 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
56 static GdkPixmap
*hatches
[num_hatches
];
57 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
59 extern GtkWidget
*wxGetRootWindow();
61 //-----------------------------------------------------------------------------
63 //-----------------------------------------------------------------------------
65 const double RAD2DEG
= 180.0 / M_PI
;
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
72 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
74 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
76 //-----------------------------------------------------------------------------
77 // temporary implementation of the missing GDK function
78 //-----------------------------------------------------------------------------
80 #include "gdk/gdkprivate.h"
82 void gdk_wx_draw_bitmap(GdkDrawable
*drawable
,
92 gint src_width
, src_height
;
94 GdkWindowPrivate
*drawable_private
;
95 GdkWindowPrivate
*src_private
;
96 GdkGCPrivate
*gc_private
;
99 g_return_if_fail (drawable
!= NULL
);
100 g_return_if_fail (src
!= NULL
);
101 g_return_if_fail (gc
!= NULL
);
104 if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
))
107 gdk_drawable_get_size(src
, &src_width
, &src_height
);
109 drawable_private
= (GdkWindowPrivate
*) drawable
;
110 src_private
= (GdkWindowPrivate
*) src
;
111 if (drawable_private
->destroyed
|| src_private
->destroyed
)
114 src_width
= src_private
->width
;
115 src_height
= src_private
->height
;
117 gc_private
= (GdkGCPrivate
*) gc
;
120 if (width
== -1) width
= src_width
;
121 if (height
== -1) height
= src_height
;
124 XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
),
126 GDK_WINDOW_XID(drawable
),
133 XCopyPlane( drawable_private
->xdisplay
,
134 src_private
->xwindow
,
135 drawable_private
->xwindow
,
144 //-----------------------------------------------------------------------------
145 // Implement Pool of Graphic contexts. Creating them takes too much time.
146 //-----------------------------------------------------------------------------
148 #define GC_POOL_SIZE 200
174 #define GC_POOL_ALLOC_SIZE 100
176 static int wxGCPoolSize
= 0;
178 static wxGC
*wxGCPool
= NULL
;
180 static void wxInitGCPool()
182 // This really could wait until the first call to
183 // wxGetPoolGC, but we will make the first allocation
184 // now when other initialization is being performed.
186 // Set initial pool size.
187 wxGCPoolSize
= GC_POOL_ALLOC_SIZE
;
189 // Allocate initial pool.
190 wxGCPool
= (wxGC
*)malloc(wxGCPoolSize
* sizeof(wxGC
));
191 if (wxGCPool
== NULL
)
193 // If we cannot malloc, then fail with error
194 // when debug is enabled. If debug is not enabled,
195 // the problem will eventually get caught
197 wxFAIL_MSG( wxT("Cannot allocate GC pool") );
201 // Zero initial pool.
202 memset(wxGCPool
, 0, wxGCPoolSize
* sizeof(wxGC
));
205 static void wxCleanUpGCPool()
207 for (int i
= 0; i
< wxGCPoolSize
; i
++)
209 if (wxGCPool
[i
].m_gc
)
210 gdk_gc_unref( wxGCPool
[i
].m_gc
);
218 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
222 // Look for an available GC.
223 for (int i
= 0; i
< wxGCPoolSize
; i
++)
225 if (!wxGCPool
[i
].m_gc
)
227 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
228 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
229 wxGCPool
[i
].m_type
= type
;
230 wxGCPool
[i
].m_used
= FALSE
;
232 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
234 wxGCPool
[i
].m_used
= TRUE
;
235 return wxGCPool
[i
].m_gc
;
239 // We did not find an available GC.
240 // We need to grow the GC pool.
241 pptr
= (wxGC
*)realloc(wxGCPool
,
242 (wxGCPoolSize
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
));
245 // Initialize newly allocated pool.
247 memset(&wxGCPool
[wxGCPoolSize
], 0,
248 GC_POOL_ALLOC_SIZE
*sizeof(wxGC
));
250 // Initialize entry we will return.
251 wxGCPool
[wxGCPoolSize
].m_gc
= gdk_gc_new( window
);
252 gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE
);
253 wxGCPool
[wxGCPoolSize
].m_type
= type
;
254 wxGCPool
[wxGCPoolSize
].m_used
= TRUE
;
256 // Set new value of pool size.
257 wxGCPoolSize
+= GC_POOL_ALLOC_SIZE
;
259 // Return newly allocated entry.
260 return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
;
263 // The realloc failed. Fall through to error.
264 wxFAIL_MSG( wxT("No GC available") );
266 return (GdkGC
*) NULL
;
269 static void wxFreePoolGC( GdkGC
*gc
)
271 for (int i
= 0; i
< wxGCPoolSize
; i
++)
273 if (wxGCPool
[i
].m_gc
== gc
)
275 wxGCPool
[i
].m_used
= FALSE
;
280 wxFAIL_MSG( wxT("Wrong GC") );
283 //-----------------------------------------------------------------------------
285 //-----------------------------------------------------------------------------
287 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
289 wxWindowDC::wxWindowDC()
291 m_penGC
= (GdkGC
*) NULL
;
292 m_brushGC
= (GdkGC
*) NULL
;
293 m_textGC
= (GdkGC
*) NULL
;
294 m_bgGC
= (GdkGC
*) NULL
;
295 m_cmap
= (GdkColormap
*) NULL
;
297 m_isScreenDC
= FALSE
;
298 m_owner
= (wxWindow
*)NULL
;
300 m_context
= (PangoContext
*)NULL
;
301 m_fontdesc
= (PangoFontDescription
*)NULL
;
305 wxWindowDC::wxWindowDC( wxWindow
*window
)
307 wxASSERT_MSG( window
, wxT("DC needs a window") );
309 m_penGC
= (GdkGC
*) NULL
;
310 m_brushGC
= (GdkGC
*) NULL
;
311 m_textGC
= (GdkGC
*) NULL
;
312 m_bgGC
= (GdkGC
*) NULL
;
313 m_cmap
= (GdkColormap
*) NULL
;
314 m_owner
= (wxWindow
*)NULL
;
316 m_isScreenDC
= FALSE
;
317 m_font
= window
->GetFont();
319 GtkWidget
*widget
= window
->m_wxwindow
;
321 // some controls don't have m_wxwindow - like wxStaticBox, but the user
322 // code should still be able to create wxClientDCs for them, so we will
323 // use the parent window here then
326 window
= window
->GetParent();
327 widget
= window
->m_wxwindow
;
330 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
333 m_context
= gtk_widget_get_pango_context( widget
);
335 m_fontdesc
= widget
->style
->font_desc
;
338 GtkPizza
*pizza
= GTK_PIZZA( widget
);
339 m_window
= pizza
->bin_window
;
344 /* don't report problems */
350 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
354 /* this must be done after SetUpDC, bacause SetUpDC calls the
355 repective SetBrush, SetPen, SetBackground etc functions
356 to set up the DC. SetBackground call m_owner->SetBackground
357 and this might not be desired as the standard dc background
358 is white whereas a window might assume gray to be the
359 standard (as e.g. wxStatusBar) */
364 wxWindowDC::~wxWindowDC()
369 void wxWindowDC::SetUpDC()
373 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
377 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
378 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
379 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
380 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
383 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
385 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
386 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
387 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
388 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
392 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
393 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
394 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
395 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
398 /* background colour */
399 m_backgroundBrush
= *wxWHITE_BRUSH
;
400 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
401 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
404 m_textForegroundColour
.CalcPixel( m_cmap
);
405 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
407 m_textBackgroundColour
.CalcPixel( m_cmap
);
408 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
410 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
413 m_pen
.GetColour().CalcPixel( m_cmap
);
414 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
415 gdk_gc_set_background( m_penGC
, bg_col
);
417 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
420 m_brush
.GetColour().CalcPixel( m_cmap
);
421 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
422 gdk_gc_set_background( m_brushGC
, bg_col
);
424 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
427 gdk_gc_set_background( m_bgGC
, bg_col
);
428 gdk_gc_set_foreground( m_bgGC
, bg_col
);
430 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
433 gdk_gc_set_function( m_textGC
, GDK_COPY
);
434 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
435 gdk_gc_set_function( m_penGC
, GDK_COPY
);
438 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
439 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
440 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
441 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
445 hatch_bitmap
= hatches
;
446 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
447 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
448 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
449 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
450 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
451 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
455 void wxWindowDC::DoGetSize( int* width
, int* height
) const
457 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
459 m_owner
->GetSize(width
, height
);
462 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
463 const wxColour
& col
, int style
);
465 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
466 const wxColour
& col
, int style
)
468 return wxDoFloodFill(this, x
, y
, col
, style
);
471 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
473 // Generic (and therefore rather inefficient) method.
474 // Could be improved.
476 wxBitmap
bitmap(1, 1);
477 memdc
.SelectObject(bitmap
);
478 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
479 memdc
.SelectObject(wxNullBitmap
);
481 wxImage image
= bitmap
.ConvertToImage();
482 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
486 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
488 wxCHECK_RET( Ok(), wxT("invalid window dc") );
490 if (m_pen
.GetStyle() != wxTRANSPARENT
)
493 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
495 CalcBoundingBox(x1
, y1
);
496 CalcBoundingBox(x2
, y2
);
500 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
502 wxCHECK_RET( Ok(), wxT("invalid window dc") );
504 if (m_pen
.GetStyle() != wxTRANSPARENT
)
509 wxCoord xx
= XLOG2DEV(x
);
510 wxCoord yy
= YLOG2DEV(y
);
513 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
514 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
519 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
520 wxCoord xc
, wxCoord yc
)
522 wxCHECK_RET( Ok(), wxT("invalid window dc") );
524 wxCoord xx1
= XLOG2DEV(x1
);
525 wxCoord yy1
= YLOG2DEV(y1
);
526 wxCoord xx2
= XLOG2DEV(x2
);
527 wxCoord yy2
= YLOG2DEV(y2
);
528 wxCoord xxc
= XLOG2DEV(xc
);
529 wxCoord yyc
= YLOG2DEV(yc
);
530 double dx
= xx1
- xxc
;
531 double dy
= yy1
- yyc
;
532 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
533 wxCoord r
= (wxCoord
)radius
;
534 double radius1
, radius2
;
536 if (xx1
== xx2
&& yy1
== yy2
)
544 radius1
= radius2
= 0.0;
548 radius1
= (xx1
- xxc
== 0) ?
549 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
550 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
551 radius2
= (xx2
- xxc
== 0) ?
552 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
553 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
555 wxCoord alpha1
= wxCoord(radius1
* 64.0);
556 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
557 while (alpha2
<= 0) alpha2
+= 360*64;
558 while (alpha1
> 360*64) alpha1
-= 360*64;
562 if (m_brush
.GetStyle() != wxTRANSPARENT
)
564 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
566 gdk_gc_set_ts_origin( m_textGC
,
567 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
568 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
569 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
570 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
572 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
574 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
575 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
576 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
578 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
580 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
581 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
582 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
584 if (m_brush
.GetStyle() == wxSTIPPLE
)
586 gdk_gc_set_ts_origin( m_brushGC
,
587 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
588 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
589 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
590 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
594 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
598 if (m_pen
.GetStyle() != wxTRANSPARENT
)
600 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
602 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
603 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
607 CalcBoundingBox (x1
, y1
);
608 CalcBoundingBox (x2
, y2
);
611 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
613 wxCHECK_RET( Ok(), wxT("invalid window dc") );
615 wxCoord xx
= XLOG2DEV(x
);
616 wxCoord yy
= YLOG2DEV(y
);
617 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
618 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
620 // CMB: handle -ve width and/or height
621 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
622 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
626 wxCoord start
= wxCoord(sa
* 64.0);
627 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
629 if (m_brush
.GetStyle() != wxTRANSPARENT
)
631 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
633 gdk_gc_set_ts_origin( m_textGC
,
634 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
635 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
636 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
637 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
639 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
641 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
642 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
643 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
645 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
647 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
648 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
649 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
651 if (m_brush
.GetStyle() == wxSTIPPLE
)
653 gdk_gc_set_ts_origin( m_brushGC
,
654 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
655 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
656 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
657 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
661 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
665 if (m_pen
.GetStyle() != wxTRANSPARENT
)
666 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
669 CalcBoundingBox (x
, y
);
670 CalcBoundingBox (x
+ width
, y
+ height
);
673 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
675 wxCHECK_RET( Ok(), wxT("invalid window dc") );
677 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
678 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
680 CalcBoundingBox (x
, y
);
683 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
685 wxCHECK_RET( Ok(), wxT("invalid window dc") );
687 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
690 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
692 for (int i
= 0; i
< n
-1; i
++)
694 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
695 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
696 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
697 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
700 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
702 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
706 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
708 wxCHECK_RET( Ok(), wxT("invalid window dc") );
712 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
714 for (i
= 0 ; i
< n
; i
++)
716 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
717 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
719 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
724 if (m_brush
.GetStyle() != wxTRANSPARENT
)
726 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
728 gdk_gc_set_ts_origin( m_textGC
,
729 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
730 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
731 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
732 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
734 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
736 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
737 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
738 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
740 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
742 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
743 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
744 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
746 if (m_brush
.GetStyle() == wxSTIPPLE
)
748 gdk_gc_set_ts_origin( m_brushGC
,
749 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
750 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
751 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
752 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
756 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
760 if (m_pen
.GetStyle() != wxTRANSPARENT
)
762 for (i
= 0 ; i
< n
; i
++)
764 gdk_draw_line( m_window
, m_penGC
,
767 gdkpoints
[(i
+1)%n
].x
,
768 gdkpoints
[(i
+1)%n
].y
);
776 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
778 wxCHECK_RET( Ok(), wxT("invalid window dc") );
780 wxCoord xx
= XLOG2DEV(x
);
781 wxCoord yy
= YLOG2DEV(y
);
782 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
783 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
785 // CMB: draw nothing if transformed w or h is 0
786 if (ww
== 0 || hh
== 0) return;
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
; }
794 if (m_brush
.GetStyle() != wxTRANSPARENT
)
796 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
798 gdk_gc_set_ts_origin( m_textGC
,
799 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
800 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
801 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
802 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
804 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
806 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
807 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
808 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
810 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
812 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
813 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
814 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
816 if (m_brush
.GetStyle() == wxSTIPPLE
)
818 gdk_gc_set_ts_origin( m_brushGC
,
819 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
820 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
821 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
822 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
826 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
830 if (m_pen
.GetStyle() != wxTRANSPARENT
)
831 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
834 CalcBoundingBox( x
, y
);
835 CalcBoundingBox( x
+ width
, y
+ height
);
838 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
840 wxCHECK_RET( Ok(), wxT("invalid window dc") );
842 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
844 wxCoord xx
= XLOG2DEV(x
);
845 wxCoord yy
= YLOG2DEV(y
);
846 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
847 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
848 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
850 // CMB: handle -ve width and/or height
851 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
852 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
854 // CMB: if radius is zero use DrawRectangle() instead to avoid
855 // X drawing errors with small radii
858 DrawRectangle( x
, y
, width
, height
);
862 // CMB: draw nothing if transformed w or h is 0
863 if (ww
== 0 || hh
== 0) return;
865 // CMB: adjust size if outline is drawn otherwise the result is
866 // 1 pixel too wide and high
867 if (m_pen
.GetStyle() != wxTRANSPARENT
)
875 // CMB: ensure dd is not larger than rectangle otherwise we
876 // get an hour glass shape
878 if (dd
> ww
) dd
= ww
;
879 if (dd
> hh
) dd
= hh
;
882 if (m_brush
.GetStyle() != wxTRANSPARENT
)
884 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
886 gdk_gc_set_ts_origin( m_textGC
,
887 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
888 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
889 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
890 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
891 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
892 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
893 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
894 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
895 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
897 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
899 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
900 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
901 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
902 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
903 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
904 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
905 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
906 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
908 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
910 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
911 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
912 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
913 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
914 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
915 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
916 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
917 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
919 if (m_brush
.GetStyle() == wxSTIPPLE
)
921 gdk_gc_set_ts_origin( m_brushGC
,
922 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
923 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
924 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
925 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
926 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
927 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
928 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
929 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
930 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
934 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
935 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
936 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
937 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
938 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
939 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
943 if (m_pen
.GetStyle() != wxTRANSPARENT
)
945 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
946 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
947 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
948 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
949 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
950 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
951 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
952 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
956 // this ignores the radius
957 CalcBoundingBox( x
, y
);
958 CalcBoundingBox( x
+ width
, y
+ height
);
961 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
963 wxCHECK_RET( Ok(), wxT("invalid window dc") );
965 wxCoord xx
= XLOG2DEV(x
);
966 wxCoord yy
= YLOG2DEV(y
);
967 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
968 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
970 // CMB: handle -ve width and/or height
971 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
972 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
976 if (m_brush
.GetStyle() != wxTRANSPARENT
)
978 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
980 gdk_gc_set_ts_origin( m_textGC
,
981 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
982 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
983 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
984 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
986 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
988 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
989 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
990 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
992 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
994 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
995 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
996 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
998 if (m_brush
.GetStyle() == wxSTIPPLE
)
1000 gdk_gc_set_ts_origin( m_brushGC
,
1001 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1002 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1003 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1004 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1008 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1012 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1013 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1016 CalcBoundingBox( x
, y
);
1017 CalcBoundingBox( x
+ width
, y
+ height
);
1020 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1022 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1023 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1026 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1027 wxCoord x
, wxCoord y
,
1030 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1032 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1034 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1036 /* scale/translate size and position */
1037 int xx
= XLOG2DEV(x
);
1038 int yy
= YLOG2DEV(y
);
1040 int w
= bitmap
.GetWidth();
1041 int h
= bitmap
.GetHeight();
1043 CalcBoundingBox( x
, y
);
1044 CalcBoundingBox( x
+ w
, y
+ h
);
1046 if (!m_window
) return;
1048 int ww
= XLOG2DEVREL(w
);
1049 int hh
= YLOG2DEVREL(h
);
1051 /* compare to current clipping region */
1052 if (!m_currentClippingRegion
.IsNull())
1054 wxRegion
tmp( xx
,yy
,ww
,hh
);
1055 tmp
.Intersect( m_currentClippingRegion
);
1060 /* scale bitmap if required */
1061 wxBitmap use_bitmap
;
1062 if ((w
!= ww
) || (h
!= hh
))
1064 wxImage image
= bitmap
.ConvertToImage();
1065 image
.Rescale( ww
, hh
);
1067 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1069 use_bitmap
= wxBitmap(image
);
1073 use_bitmap
= bitmap
;
1076 /* apply mask if any */
1077 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1078 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1080 if (useMask
&& mask
)
1082 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1083 #ifndef __WXGTK20__ // TODO fix crash
1084 if (!m_currentClippingRegion
.IsNull())
1087 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1088 GdkGC
*gc
= gdk_gc_new( new_mask
);
1090 gdk_gc_set_foreground( gc
, &col
);
1091 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1093 gdk_gc_set_background( gc
, &col
);
1095 gdk_gc_set_foreground( gc
, &col
);
1096 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1097 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1098 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1099 gdk_gc_set_stipple( gc
, mask
);
1100 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1107 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1109 gdk_gc_set_clip_mask( m_textGC
, mask
);
1110 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1115 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1117 gdk_gc_set_clip_mask( m_penGC
, mask
);
1118 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1122 gdk_bitmap_unref( new_mask
);
1125 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1126 drawing a mono-bitmap (XBitmap) we use the current text GC */
1128 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1130 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1132 /* remove mask again if any */
1133 if (useMask
&& mask
)
1137 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1138 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1139 if (!m_currentClippingRegion
.IsNull())
1140 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1144 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1145 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1146 if (!m_currentClippingRegion
.IsNull())
1147 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1152 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1153 wxCoord width
, wxCoord height
,
1155 wxCoord xsrc
, wxCoord ysrc
,
1158 wxCoord xsrcMask
, wxCoord ysrcMask
)
1160 /* this is the nth try to get this utterly useless function to
1161 work. it now completely ignores the scaling or translation
1162 of the source dc, but scales correctly on the target dc and
1163 knows about possible mask information in a memory dc. */
1165 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1167 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1169 if (!m_window
) return FALSE
;
1172 // transform the source DC coords to the device ones
1173 xsrc
= source
->XLOG2DEV(xsrc
);
1174 ysrc
= source
->YLOG2DEV(ysrc
);
1177 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1178 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1180 bool use_bitmap_method
= FALSE
;
1181 bool is_mono
= FALSE
;
1183 /* TODO: use the mask origin when drawing transparently */
1184 if (xsrcMask
== -1 && ysrcMask
== -1)
1186 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1189 if (srcDC
->m_isMemDC
)
1191 if (!memDC
->m_selected
.Ok()) return FALSE
;
1193 /* we use the "XCopyArea" way to copy a memory dc into
1194 y different window if the memory dc BOTH
1195 a) doesn't have any mask or its mask isn't used
1199 if (useMask
&& (memDC
->m_selected
.GetMask()))
1201 /* we HAVE TO use the direct way for memory dcs
1202 that have mask since the XCopyArea doesn't know
1204 use_bitmap_method
= TRUE
;
1206 else if (memDC
->m_selected
.GetDepth() == 1)
1208 /* we HAVE TO use the direct way for memory dcs
1209 that are bitmaps because XCopyArea doesn't cope
1210 with different bit depths */
1212 use_bitmap_method
= TRUE
;
1214 else if ((xsrc
== 0) && (ysrc
== 0) &&
1215 (width
== memDC
->m_selected
.GetWidth()) &&
1216 (height
== memDC
->m_selected
.GetHeight()))
1218 /* we SHOULD use the direct way if all of the bitmap
1219 in the memory dc is copied in which case XCopyArea
1220 wouldn't be able able to boost performace by reducing
1221 the area to be scaled */
1222 use_bitmap_method
= TRUE
;
1226 use_bitmap_method
= FALSE
;
1230 CalcBoundingBox( xdest
, ydest
);
1231 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1233 /* scale/translate size and position */
1234 wxCoord xx
= XLOG2DEV(xdest
);
1235 wxCoord yy
= YLOG2DEV(ydest
);
1237 wxCoord ww
= XLOG2DEVREL(width
);
1238 wxCoord hh
= YLOG2DEVREL(height
);
1240 /* compare to current clipping region */
1241 if (!m_currentClippingRegion
.IsNull())
1243 wxRegion
tmp( xx
,yy
,ww
,hh
);
1244 tmp
.Intersect( m_currentClippingRegion
);
1249 int old_logical_func
= m_logicalFunction
;
1250 SetLogicalFunction( logical_func
);
1252 if (use_bitmap_method
)
1254 /* scale/translate bitmap size */
1255 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1256 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1258 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1259 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1261 /* scale bitmap if required */
1262 wxBitmap use_bitmap
;
1264 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1266 wxImage image
= memDC
->m_selected
.ConvertToImage();
1267 image
= image
.Scale( bm_ww
, bm_hh
);
1270 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1272 use_bitmap
= wxBitmap(image
);
1276 use_bitmap
= memDC
->m_selected
;
1279 /* apply mask if any */
1280 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1281 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1283 if (useMask
&& mask
)
1285 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1286 #ifndef __WXGTK20__ // TODO fix crash
1287 if (!m_currentClippingRegion
.IsNull())
1290 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1291 GdkGC
*gc
= gdk_gc_new( new_mask
);
1293 gdk_gc_set_foreground( gc
, &col
);
1294 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1296 gdk_gc_set_background( gc
, &col
);
1298 gdk_gc_set_foreground( gc
, &col
);
1299 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1300 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1301 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1302 gdk_gc_set_stipple( gc
, mask
);
1303 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1310 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1312 gdk_gc_set_clip_mask( m_textGC
, mask
);
1313 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1318 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1320 gdk_gc_set_clip_mask( m_penGC
, mask
);
1321 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1324 gdk_bitmap_unref( new_mask
);
1327 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1328 drawing a mono-bitmap (XBitmap) we use the current text GC */
1331 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1333 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1335 /* remove mask again if any */
1336 if (useMask
&& mask
)
1340 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1341 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1342 if (!m_currentClippingRegion
.IsNull())
1343 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1347 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1348 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1349 if (!m_currentClippingRegion
.IsNull())
1350 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1354 else /* use_bitmap_method */
1356 if ((width
!= ww
) || (height
!= hh
))
1358 /* draw source window into a bitmap as we cannot scale
1359 a window in contrast to a bitmap. this would actually
1360 work with memory dcs as well, but we'd lose the mask
1361 information and waste one step in this process since
1362 a memory already has a bitmap. all this is slightly
1363 inefficient as we could take an XImage directly from
1364 an X window, but we'd then also have to care that
1365 the window is not outside the screen (in which case
1366 we'd get a BadMatch or what not).
1367 Is a double XGetImage and combined XGetPixel and
1368 XPutPixel really faster? I'm not sure. look at wxXt
1369 for a different implementation of the same problem. */
1371 wxBitmap
bitmap( width
, height
);
1373 /* copy including child window contents */
1374 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1375 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1377 xsrc
, ysrc
, width
, height
);
1378 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1381 wxImage image
= bitmap
.ConvertToImage();
1382 image
= image
.Scale( ww
, hh
);
1384 /* convert to bitmap */
1385 bitmap
= wxBitmap(image
);
1387 /* draw scaled bitmap */
1388 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1393 /* No scaling and not a memory dc with a mask either */
1395 /* copy including child window contents */
1396 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1397 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1399 xsrc
, ysrc
, width
, height
);
1400 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1404 SetLogicalFunction( old_logical_func
);
1408 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1410 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1412 if (!m_window
) return;
1414 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1416 wxCHECK_RET( font
, wxT("invalid font") );
1418 #if defined(__WXGTK20__)
1419 wxCHECK_RET( m_context
, wxT("no Pango context") );
1425 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1426 // TODO: the layout engine should be abstracted at a higher level!
1427 PangoLayout
*layout
= pango_layout_new(m_context
);
1428 pango_layout_set_font_description(layout
, m_fontdesc
);
1430 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
1431 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1433 PangoLayoutLine
*line
= (PangoLayoutLine
*)pango_layout_get_lines(layout
)->data
;
1434 PangoRectangle rect
;
1435 pango_layout_line_get_extents(line
, NULL
, &rect
);
1436 wxCoord width
= rect
.width
;
1437 wxCoord height
= rect
.height
;
1438 gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout
);
1440 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1441 wxCoord height
= font
->ascent
+ font
->descent
;
1443 if ( m_backgroundMode
== wxSOLID
)
1445 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1446 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1447 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1449 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1451 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1452 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1453 properties (see wxXt implementation) */
1454 if (m_font
.GetUnderlined())
1456 wxCoord ul_y
= y
+ font
->ascent
;
1457 if (font
->descent
> 0) ul_y
++;
1458 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1460 #endif // GTK+ 2.0/1.x
1462 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1463 g_object_unref( G_OBJECT( layout
) );
1466 width
= wxCoord(width
/ m_scaleX
);
1467 height
= wxCoord(height
/ m_scaleY
);
1468 CalcBoundingBox (x
+ width
, y
+ height
);
1469 CalcBoundingBox (x
, y
);
1472 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1476 DrawText(text
, x
, y
);
1480 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1482 if (!m_window
) return;
1484 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1486 wxCHECK_RET( font
, wxT("invalid font") );
1488 // the size of the text
1489 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1490 wxCoord h
= font
->ascent
+ font
->descent
;
1492 // draw the string normally
1495 dc
.SelectObject(src
);
1496 dc
.SetFont(GetFont());
1497 dc
.SetBackground(*wxWHITE_BRUSH
);
1498 dc
.SetBrush(*wxBLACK_BRUSH
);
1500 dc
.DrawText(text
, 0, 0);
1501 dc
.SelectObject(wxNullBitmap
);
1503 // Calculate the size of the rotated bounding box.
1504 double rad
= DegToRad(angle
);
1505 double dx
= cos(rad
),
1508 // the rectngle vertices are counted clockwise with the first one being at
1509 // (0, 0) (or, rather, at (x, y))
1511 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1514 double x3
= x4
+ x2
,
1518 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1519 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1520 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1521 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1523 // prepare to blit-with-rotate the bitmap to the DC
1524 wxImage image
= src
.ConvertToImage();
1526 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1527 *colBack
= m_textBackgroundColour
.GetColor();
1529 bool textColSet
= TRUE
;
1531 unsigned char *data
= image
.GetData();
1533 // paint pixel by pixel
1534 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1536 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1538 // transform source coords to dest coords
1539 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1540 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1541 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1542 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1545 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1546 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1548 // change colour if needed
1549 if ( textPixel
!= textColSet
)
1551 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1554 textColSet
= textPixel
;
1557 // don't use DrawPoint() because it uses the current pen
1558 // colour, and we don't need it here
1559 gdk_draw_point( m_window
, m_textGC
,
1560 XLOG2DEV(x
) + dstX
, YLOG2DEV(y
) + dstY
);
1565 // it would be better to draw with non underlined font and draw the line
1566 // manually here (it would be more straight...)
1568 if ( m_font
.GetUnderlined() )
1570 gdk_draw_line( m_window
, m_textGC
,
1571 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1572 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1576 // restore the font colour
1577 gdk_gc_set_foreground( m_textGC
, colText
);
1579 // update the bounding box
1580 CalcBoundingBox(x
+ minX
, y
+ minY
);
1581 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1584 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1585 wxCoord
*width
, wxCoord
*height
,
1586 wxCoord
*descent
, wxCoord
*externalLeading
,
1587 wxFont
*theFont
) const
1589 wxFont fontToUse
= m_font
;
1590 if (theFont
) fontToUse
= *theFont
;
1591 if (string
.IsEmpty())
1593 if (width
) (*width
) = 0;
1594 if (height
) (*height
) = 0;
1599 PangoFontDescription
*desc
= fontToUse
.GetNativeFontInfo()->description
;
1600 PangoLayout
*layout
= pango_layout_new(m_context
);
1601 pango_layout_set_font_description(layout
, desc
);
1603 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
1604 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1606 PangoLayoutLine
*line
= (PangoLayoutLine
*)pango_layout_get_lines(layout
)->data
;
1608 PangoRectangle rect
;
1609 pango_layout_line_get_extents(line
, NULL
, &rect
);
1612 if (width
) (*width
) = (wxCoord
) (rect
.width
/ PANGO_SCALE
);
1613 if (height
) (*height
) = (wxCoord
) (rect
.height
/ PANGO_SCALE
);
1616 // Do something about metrics here
1619 if (externalLeading
) (*externalLeading
) = 0; // ??
1621 g_object_unref( G_OBJECT( layout
) );
1623 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1624 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1625 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1626 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1627 if (externalLeading
) (*externalLeading
) = 0; // ??
1631 wxCoord
wxWindowDC::GetCharWidth() const
1633 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1634 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1636 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1639 wxCoord
wxWindowDC::GetCharHeight() const
1641 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1642 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1644 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1647 void wxWindowDC::Clear()
1649 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1651 if (!m_window
) return;
1653 // VZ: the code below results in infinite recursion and crashes when
1654 // dc.Clear() is done from OnPaint() so I disable it for now.
1655 // I don't know what the correct fix is but Clear() surely should not
1656 // reenter OnPaint()!
1658 /* - we either are a memory dc or have a window as the
1659 owner. anything else shouldn't happen.
1660 - we don't use gdk_window_clear() as we don't set
1661 the window's background colour anymore. it is too
1662 much pain to keep the DC's and the window's back-
1663 ground colour in synch. */
1674 GetSize( &width
, &height
);
1675 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1680 GetSize( &width
, &height
);
1681 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1685 void wxWindowDC::SetFont( const wxFont
&font
)
1687 // It is common practice to set the font to wxNullFont, so
1688 // don't consider it to be an error
1689 // wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") );
1693 m_fontdesc
= m_font
.GetNativeFontInfo()->description
;
1697 void wxWindowDC::SetPen( const wxPen
&pen
)
1699 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1701 if (m_pen
== pen
) return;
1705 if (!m_pen
.Ok()) return;
1707 if (!m_window
) return;
1709 gint width
= m_pen
.GetWidth();
1712 // CMB: if width is non-zero scale it with the dc
1717 // X doesn't allow different width in x and y and so we take
1720 ( fabs((double) XLOG2DEVREL(width
)) +
1721 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1725 static const wxGTKDash dotted
[] = {1, 1};
1726 static const wxGTKDash short_dashed
[] = {2, 2};
1727 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1728 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1730 // We express dash pattern in pen width unit, so we are
1731 // independent of zoom factor and so on...
1733 const wxGTKDash
*req_dash
;
1735 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1736 switch (m_pen
.GetStyle())
1740 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1741 req_nb_dash
= m_pen
.GetDashCount();
1742 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1747 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1754 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1756 req_dash
= wxCoord_dashed
;
1761 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1763 req_dash
= short_dashed
;
1768 // lineStyle = GDK_LINE_DOUBLE_DASH;
1769 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1771 req_dash
= dotted_dashed
;
1776 case wxSTIPPLE_MASK_OPAQUE
:
1781 lineStyle
= GDK_LINE_SOLID
;
1782 req_dash
= (wxGTKDash
*)NULL
;
1788 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1789 if (req_dash
&& req_nb_dash
)
1791 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1794 for (int i
= 0; i
< req_nb_dash
; i
++)
1795 real_req_dash
[i
] = req_dash
[i
] * width
;
1796 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1797 delete[] real_req_dash
;
1801 // No Memory. We use non-scaled dash pattern...
1802 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1807 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1808 switch (m_pen
.GetCap())
1810 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1811 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1818 capStyle
= GDK_CAP_NOT_LAST
;
1822 capStyle
= GDK_CAP_ROUND
;
1828 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1829 switch (m_pen
.GetJoin())
1831 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1832 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1834 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1837 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1839 m_pen
.GetColour().CalcPixel( m_cmap
);
1840 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1843 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1845 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1847 if (m_brush
== brush
) return;
1851 if (!m_brush
.Ok()) return;
1853 if (!m_window
) return;
1855 m_brush
.GetColour().CalcPixel( m_cmap
);
1856 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1858 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1860 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1862 if (m_brush
.GetStipple()->GetPixmap())
1864 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1865 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1869 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1870 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1874 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1876 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1877 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1880 if (IS_HATCH(m_brush
.GetStyle()))
1882 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1883 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1884 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1888 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1890 /* CMB 21/7/98: Added SetBackground. Sets background brush
1891 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1893 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1895 if (m_backgroundBrush
== brush
) return;
1897 m_backgroundBrush
= brush
;
1899 if (!m_backgroundBrush
.Ok()) return;
1901 if (!m_window
) return;
1903 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1904 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1905 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1906 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1907 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1909 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1911 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1913 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1915 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1916 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1920 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1921 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1925 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1927 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1928 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1929 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1933 void wxWindowDC::SetLogicalFunction( int function
)
1935 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1937 if (m_logicalFunction
== function
)
1940 // VZ: shouldn't this be a CHECK?
1944 GdkFunction mode
= GDK_COPY
;
1947 case wxXOR
: mode
= GDK_XOR
; break;
1948 case wxINVERT
: mode
= GDK_INVERT
; break;
1949 #if (GTK_MINOR_VERSION > 0)
1950 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1951 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1952 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1953 case wxSET
: mode
= GDK_SET
; break;
1954 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1955 case wxAND
: mode
= GDK_AND
; break;
1956 case wxOR
: mode
= GDK_OR
; break;
1957 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1958 case wxNAND
: mode
= GDK_NAND
; break;
1959 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1960 case wxCOPY
: mode
= GDK_COPY
; break;
1961 case wxNO_OP
: mode
= GDK_NOOP
; break;
1962 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1964 // unsupported by GTK
1965 case wxNOR
: mode
= GDK_COPY
; break;
1969 wxFAIL_MSG( wxT("unsupported logical function") );
1974 m_logicalFunction
= function
;
1976 gdk_gc_set_function( m_penGC
, mode
);
1977 gdk_gc_set_function( m_brushGC
, mode
);
1979 // to stay compatible with wxMSW, we don't apply ROPs to the text
1980 // operations (i.e. DrawText/DrawRotatedText).
1981 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1982 gdk_gc_set_function( m_textGC
, mode
);
1985 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1987 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1989 // don't set m_textForegroundColour to an invalid colour as we'd crash
1990 // later then (we use m_textForegroundColour.GetColor() without checking
1992 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1995 m_textForegroundColour
= col
;
1999 m_textForegroundColour
.CalcPixel( m_cmap
);
2000 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
2004 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2006 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2009 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
2012 m_textBackgroundColour
= col
;
2016 m_textBackgroundColour
.CalcPixel( m_cmap
);
2017 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
2021 void wxWindowDC::SetBackgroundMode( int mode
)
2023 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2025 m_backgroundMode
= mode
;
2027 if (!m_window
) return;
2029 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2030 // transparent/solid background mode
2032 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2034 gdk_gc_set_fill( m_brushGC
,
2035 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2039 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2041 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2044 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2046 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2048 if (!m_window
) return;
2051 rect
.x
= XLOG2DEV(x
);
2052 rect
.y
= YLOG2DEV(y
);
2053 rect
.width
= XLOG2DEVREL(width
);
2054 rect
.height
= YLOG2DEVREL(height
);
2056 if (!m_currentClippingRegion
.IsNull())
2057 m_currentClippingRegion
.Intersect( rect
);
2059 m_currentClippingRegion
.Union( rect
);
2061 #if USE_PAINT_REGION
2062 if (!m_paintClippingRegion
.IsNull())
2063 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2066 wxCoord xx
, yy
, ww
, hh
;
2067 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2068 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2070 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2071 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2072 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2073 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2076 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2078 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2082 DestroyClippingRegion();
2086 if (!m_window
) return;
2088 if (!m_currentClippingRegion
.IsNull())
2089 m_currentClippingRegion
.Intersect( region
);
2091 m_currentClippingRegion
.Union( region
);
2093 #if USE_PAINT_REGION
2094 if (!m_paintClippingRegion
.IsNull())
2095 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2098 wxCoord xx
, yy
, ww
, hh
;
2099 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2100 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2102 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2103 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2104 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2105 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2108 void wxWindowDC::DestroyClippingRegion()
2110 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2112 wxDC::DestroyClippingRegion();
2114 m_currentClippingRegion
.Clear();
2116 #if USE_PAINT_REGION
2117 if (!m_paintClippingRegion
.IsEmpty())
2118 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2121 if (!m_window
) return;
2123 if (m_currentClippingRegion
.IsEmpty())
2125 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2126 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2127 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2128 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2132 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2133 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2134 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2135 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2139 void wxWindowDC::Destroy()
2141 if (m_penGC
) wxFreePoolGC( m_penGC
);
2142 m_penGC
= (GdkGC
*) NULL
;
2143 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2144 m_brushGC
= (GdkGC
*) NULL
;
2145 if (m_textGC
) wxFreePoolGC( m_textGC
);
2146 m_textGC
= (GdkGC
*) NULL
;
2147 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2148 m_bgGC
= (GdkGC
*) NULL
;
2151 void wxWindowDC::ComputeScaleAndOrigin()
2153 /* CMB: copy scale to see if it changes */
2154 double origScaleX
= m_scaleX
;
2155 double origScaleY
= m_scaleY
;
2157 wxDC::ComputeScaleAndOrigin();
2159 /* CMB: if scale has changed call SetPen to recalulate the line width */
2160 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2163 /* this is a bit artificial, but we need to force wxDC to think
2164 the pen has changed */
2171 // Resolution in pixels per logical inch
2172 wxSize
wxWindowDC::GetPPI() const
2174 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2177 int wxWindowDC::GetDepth() const
2179 wxFAIL_MSG(wxT("not implemented"));
2185 //-----------------------------------------------------------------------------
2187 //-----------------------------------------------------------------------------
2189 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2191 wxPaintDC::wxPaintDC( wxWindow
*win
)
2194 #if USE_PAINT_REGION
2195 if (!win
->m_clipPaintRegion
)
2198 m_paintClippingRegion
= win
->GetUpdateRegion();
2199 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2202 m_paintClippingRegion
= win
->GetUpdateRegion();
2203 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2206 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2208 gdk_gc_set_clip_region( m_penGC
, region
);
2209 gdk_gc_set_clip_region( m_brushGC
, region
);
2210 gdk_gc_set_clip_region( m_textGC
, region
);
2211 gdk_gc_set_clip_region( m_bgGC
, region
);
2214 #endif // USE_PAINT_REGION
2217 //-----------------------------------------------------------------------------
2219 //-----------------------------------------------------------------------------
2221 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2223 wxClientDC::wxClientDC( wxWindow
*win
)
2226 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2228 #ifdef __WXUNIVERSAL__
2229 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2230 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2231 wxSize size
= win
->GetClientSize();
2232 SetClippingRegion(wxPoint(0, 0), size
);
2233 #endif // __WXUNIVERSAL__
2236 void wxClientDC::DoGetSize(int *width
, int *height
) const
2238 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2240 m_owner
->GetClientSize( width
, height
);
2243 // ----------------------------------------------------------------------------
2245 // ----------------------------------------------------------------------------
2247 class wxDCModule
: public wxModule
2254 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2257 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2259 bool wxDCModule::OnInit()
2265 void wxDCModule::OnExit()