]>
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
= window
->GtkGetPangoDefaultContext();
334 m_fontdesc
= widget
->style
->font_desc
;
337 GtkPizza
*pizza
= GTK_PIZZA( widget
);
338 m_window
= pizza
->bin_window
;
343 /* don't report problems */
349 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
353 /* this must be done after SetUpDC, bacause SetUpDC calls the
354 repective SetBrush, SetPen, SetBackground etc functions
355 to set up the DC. SetBackground call m_owner->SetBackground
356 and this might not be desired as the standard dc background
357 is white whereas a window might assume gray to be the
358 standard (as e.g. wxStatusBar) */
363 wxWindowDC::~wxWindowDC()
368 void wxWindowDC::SetUpDC()
372 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
376 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
377 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
378 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
379 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
382 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
384 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
385 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
386 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
387 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
391 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
392 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
393 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
394 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
397 /* background colour */
398 m_backgroundBrush
= *wxWHITE_BRUSH
;
399 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
400 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
403 m_textForegroundColour
.CalcPixel( m_cmap
);
404 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
406 m_textBackgroundColour
.CalcPixel( m_cmap
);
407 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
409 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
412 m_pen
.GetColour().CalcPixel( m_cmap
);
413 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
414 gdk_gc_set_background( m_penGC
, bg_col
);
416 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
419 m_brush
.GetColour().CalcPixel( m_cmap
);
420 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
421 gdk_gc_set_background( m_brushGC
, bg_col
);
423 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
426 gdk_gc_set_background( m_bgGC
, bg_col
);
427 gdk_gc_set_foreground( m_bgGC
, bg_col
);
429 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
432 gdk_gc_set_function( m_textGC
, GDK_COPY
);
433 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
434 gdk_gc_set_function( m_penGC
, GDK_COPY
);
437 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
438 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
439 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
440 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
444 hatch_bitmap
= hatches
;
445 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
446 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
447 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
448 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
449 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
450 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
454 void wxWindowDC::DoGetSize( int* width
, int* height
) const
456 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
458 m_owner
->GetSize(width
, height
);
461 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
462 const wxColour
& col
, int style
);
464 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
465 const wxColour
& col
, int style
)
467 return wxDoFloodFill(this, x
, y
, col
, style
);
470 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
472 // Generic (and therefore rather inefficient) method.
473 // Could be improved.
475 wxBitmap
bitmap(1, 1);
476 memdc
.SelectObject(bitmap
);
477 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
478 memdc
.SelectObject(wxNullBitmap
);
480 wxImage image
= bitmap
.ConvertToImage();
481 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
485 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
487 wxCHECK_RET( Ok(), wxT("invalid window dc") );
489 if (m_pen
.GetStyle() != wxTRANSPARENT
)
492 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
494 CalcBoundingBox(x1
, y1
);
495 CalcBoundingBox(x2
, y2
);
499 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
501 wxCHECK_RET( Ok(), wxT("invalid window dc") );
503 if (m_pen
.GetStyle() != wxTRANSPARENT
)
508 wxCoord xx
= XLOG2DEV(x
);
509 wxCoord yy
= YLOG2DEV(y
);
512 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
513 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
518 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
519 wxCoord xc
, wxCoord yc
)
521 wxCHECK_RET( Ok(), wxT("invalid window dc") );
523 wxCoord xx1
= XLOG2DEV(x1
);
524 wxCoord yy1
= YLOG2DEV(y1
);
525 wxCoord xx2
= XLOG2DEV(x2
);
526 wxCoord yy2
= YLOG2DEV(y2
);
527 wxCoord xxc
= XLOG2DEV(xc
);
528 wxCoord yyc
= YLOG2DEV(yc
);
529 double dx
= xx1
- xxc
;
530 double dy
= yy1
- yyc
;
531 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
532 wxCoord r
= (wxCoord
)radius
;
533 double radius1
, radius2
;
535 if (xx1
== xx2
&& yy1
== yy2
)
543 radius1
= radius2
= 0.0;
547 radius1
= (xx1
- xxc
== 0) ?
548 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
549 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
550 radius2
= (xx2
- xxc
== 0) ?
551 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
552 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
554 wxCoord alpha1
= wxCoord(radius1
* 64.0);
555 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
556 while (alpha2
<= 0) alpha2
+= 360*64;
557 while (alpha1
> 360*64) alpha1
-= 360*64;
561 if (m_brush
.GetStyle() != wxTRANSPARENT
)
563 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
565 gdk_gc_set_ts_origin( m_textGC
,
566 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
567 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
568 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
569 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
571 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
573 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
574 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
575 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
577 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
579 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
580 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
581 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
583 if (m_brush
.GetStyle() == wxSTIPPLE
)
585 gdk_gc_set_ts_origin( m_brushGC
,
586 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
587 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
588 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
589 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
593 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
597 if (m_pen
.GetStyle() != wxTRANSPARENT
)
599 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
601 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
602 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
606 CalcBoundingBox (x1
, y1
);
607 CalcBoundingBox (x2
, y2
);
610 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
612 wxCHECK_RET( Ok(), wxT("invalid window dc") );
614 wxCoord xx
= XLOG2DEV(x
);
615 wxCoord yy
= YLOG2DEV(y
);
616 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
617 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
619 // CMB: handle -ve width and/or height
620 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
621 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
625 wxCoord start
= wxCoord(sa
* 64.0);
626 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
628 if (m_brush
.GetStyle() != wxTRANSPARENT
)
630 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
632 gdk_gc_set_ts_origin( m_textGC
,
633 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
634 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
635 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
636 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
638 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
640 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
641 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
642 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
644 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
646 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
647 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
648 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
650 if (m_brush
.GetStyle() == wxSTIPPLE
)
652 gdk_gc_set_ts_origin( m_brushGC
,
653 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
654 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
655 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
656 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
660 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
664 if (m_pen
.GetStyle() != wxTRANSPARENT
)
665 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
668 CalcBoundingBox (x
, y
);
669 CalcBoundingBox (x
+ width
, y
+ height
);
672 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
674 wxCHECK_RET( Ok(), wxT("invalid window dc") );
676 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
677 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
679 CalcBoundingBox (x
, y
);
682 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
684 wxCHECK_RET( Ok(), wxT("invalid window dc") );
686 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
689 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
691 for (int i
= 0; i
< n
-1; i
++)
693 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
694 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
695 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
696 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
699 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
701 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
705 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
707 wxCHECK_RET( Ok(), wxT("invalid window dc") );
711 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
713 for (i
= 0 ; i
< n
; i
++)
715 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
716 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
718 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
723 if (m_brush
.GetStyle() != wxTRANSPARENT
)
725 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
727 gdk_gc_set_ts_origin( m_textGC
,
728 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
729 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
730 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
731 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
733 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
735 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
736 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
737 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
739 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
741 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
742 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
743 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
745 if (m_brush
.GetStyle() == wxSTIPPLE
)
747 gdk_gc_set_ts_origin( m_brushGC
,
748 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
749 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
750 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
751 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
755 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
759 if (m_pen
.GetStyle() != wxTRANSPARENT
)
761 for (i
= 0 ; i
< n
; i
++)
763 gdk_draw_line( m_window
, m_penGC
,
766 gdkpoints
[(i
+1)%n
].x
,
767 gdkpoints
[(i
+1)%n
].y
);
775 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
777 wxCHECK_RET( Ok(), wxT("invalid window dc") );
779 wxCoord xx
= XLOG2DEV(x
);
780 wxCoord yy
= YLOG2DEV(y
);
781 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
782 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
784 // CMB: draw nothing if transformed w or h is 0
785 if (ww
== 0 || hh
== 0) return;
787 // CMB: handle -ve width and/or height
788 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
789 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
793 if (m_brush
.GetStyle() != wxTRANSPARENT
)
795 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
797 gdk_gc_set_ts_origin( m_textGC
,
798 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
799 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
800 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
801 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
803 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
805 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
806 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
807 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
809 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
811 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
812 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
813 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
815 if (m_brush
.GetStyle() == wxSTIPPLE
)
817 gdk_gc_set_ts_origin( m_brushGC
,
818 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
819 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
820 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
821 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
825 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
829 if (m_pen
.GetStyle() != wxTRANSPARENT
)
830 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
833 CalcBoundingBox( x
, y
);
834 CalcBoundingBox( x
+ width
, y
+ height
);
837 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
839 wxCHECK_RET( Ok(), wxT("invalid window dc") );
841 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
843 wxCoord xx
= XLOG2DEV(x
);
844 wxCoord yy
= YLOG2DEV(y
);
845 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
846 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
847 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
849 // CMB: handle -ve width and/or height
850 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
851 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
853 // CMB: if radius is zero use DrawRectangle() instead to avoid
854 // X drawing errors with small radii
857 DrawRectangle( x
, y
, width
, height
);
861 // CMB: draw nothing if transformed w or h is 0
862 if (ww
== 0 || hh
== 0) return;
864 // CMB: adjust size if outline is drawn otherwise the result is
865 // 1 pixel too wide and high
866 if (m_pen
.GetStyle() != wxTRANSPARENT
)
874 // CMB: ensure dd is not larger than rectangle otherwise we
875 // get an hour glass shape
877 if (dd
> ww
) dd
= ww
;
878 if (dd
> hh
) dd
= hh
;
881 if (m_brush
.GetStyle() != wxTRANSPARENT
)
883 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
885 gdk_gc_set_ts_origin( m_textGC
,
886 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
887 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
888 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
889 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
890 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
891 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
892 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
893 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
894 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
896 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
898 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
899 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
900 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
901 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
902 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
903 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
904 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
905 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
907 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
909 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
910 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
911 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
912 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
913 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
914 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
915 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
916 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
918 if (m_brush
.GetStyle() == wxSTIPPLE
)
920 gdk_gc_set_ts_origin( m_brushGC
,
921 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
922 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
923 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
924 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
925 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
926 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
927 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
928 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
929 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
933 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
934 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
935 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
936 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
937 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
938 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
942 if (m_pen
.GetStyle() != wxTRANSPARENT
)
944 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
945 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
946 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
947 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
948 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
949 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
950 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
951 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
955 // this ignores the radius
956 CalcBoundingBox( x
, y
);
957 CalcBoundingBox( x
+ width
, y
+ height
);
960 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
962 wxCHECK_RET( Ok(), wxT("invalid window dc") );
964 wxCoord xx
= XLOG2DEV(x
);
965 wxCoord yy
= YLOG2DEV(y
);
966 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
967 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
969 // CMB: handle -ve width and/or height
970 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
971 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
975 if (m_brush
.GetStyle() != wxTRANSPARENT
)
977 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
979 gdk_gc_set_ts_origin( m_textGC
,
980 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
981 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
982 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
983 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
985 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
987 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
988 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
989 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
991 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
993 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
994 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
995 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
997 if (m_brush
.GetStyle() == wxSTIPPLE
)
999 gdk_gc_set_ts_origin( m_brushGC
,
1000 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1001 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1002 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1003 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1007 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1011 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1012 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1015 CalcBoundingBox( x
, y
);
1016 CalcBoundingBox( x
+ width
, y
+ height
);
1019 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1021 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1022 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1025 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1026 wxCoord x
, wxCoord y
,
1029 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1031 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1033 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1035 /* scale/translate size and position */
1036 int xx
= XLOG2DEV(x
);
1037 int yy
= YLOG2DEV(y
);
1039 int w
= bitmap
.GetWidth();
1040 int h
= bitmap
.GetHeight();
1042 CalcBoundingBox( x
, y
);
1043 CalcBoundingBox( x
+ w
, y
+ h
);
1045 if (!m_window
) return;
1047 int ww
= XLOG2DEVREL(w
);
1048 int hh
= YLOG2DEVREL(h
);
1050 /* compare to current clipping region */
1051 if (!m_currentClippingRegion
.IsNull())
1053 wxRegion
tmp( xx
,yy
,ww
,hh
);
1054 tmp
.Intersect( m_currentClippingRegion
);
1059 /* scale bitmap if required */
1060 wxBitmap use_bitmap
;
1061 if ((w
!= ww
) || (h
!= hh
))
1063 wxImage image
= bitmap
.ConvertToImage();
1064 image
.Rescale( ww
, hh
);
1066 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1068 use_bitmap
= wxBitmap(image
);
1072 use_bitmap
= bitmap
;
1075 /* apply mask if any */
1076 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1077 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1079 if (useMask
&& mask
)
1081 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1082 #ifndef __WXGTK20__ // TODO fix crash
1083 if (!m_currentClippingRegion
.IsNull())
1086 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1087 GdkGC
*gc
= gdk_gc_new( new_mask
);
1089 gdk_gc_set_foreground( gc
, &col
);
1090 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1092 gdk_gc_set_background( gc
, &col
);
1094 gdk_gc_set_foreground( gc
, &col
);
1095 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1096 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1097 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1098 gdk_gc_set_stipple( gc
, mask
);
1099 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1106 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1108 gdk_gc_set_clip_mask( m_textGC
, mask
);
1109 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1114 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1116 gdk_gc_set_clip_mask( m_penGC
, mask
);
1117 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1121 gdk_bitmap_unref( new_mask
);
1124 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1125 drawing a mono-bitmap (XBitmap) we use the current text GC */
1127 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1129 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1131 /* remove mask again if any */
1132 if (useMask
&& mask
)
1136 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1137 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1138 if (!m_currentClippingRegion
.IsNull())
1139 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1143 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1144 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1145 if (!m_currentClippingRegion
.IsNull())
1146 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1151 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1152 wxCoord width
, wxCoord height
,
1154 wxCoord xsrc
, wxCoord ysrc
,
1157 wxCoord xsrcMask
, wxCoord ysrcMask
)
1159 /* this is the nth try to get this utterly useless function to
1160 work. it now completely ignores the scaling or translation
1161 of the source dc, but scales correctly on the target dc and
1162 knows about possible mask information in a memory dc. */
1164 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1166 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1168 if (!m_window
) return FALSE
;
1171 // transform the source DC coords to the device ones
1172 xsrc
= source
->XLOG2DEV(xsrc
);
1173 ysrc
= source
->YLOG2DEV(ysrc
);
1176 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1177 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1179 bool use_bitmap_method
= FALSE
;
1180 bool is_mono
= FALSE
;
1182 /* TODO: use the mask origin when drawing transparently */
1183 if (xsrcMask
== -1 && ysrcMask
== -1)
1185 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1188 if (srcDC
->m_isMemDC
)
1190 if (!memDC
->m_selected
.Ok()) return FALSE
;
1192 /* we use the "XCopyArea" way to copy a memory dc into
1193 y different window if the memory dc BOTH
1194 a) doesn't have any mask or its mask isn't used
1198 if (useMask
&& (memDC
->m_selected
.GetMask()))
1200 /* we HAVE TO use the direct way for memory dcs
1201 that have mask since the XCopyArea doesn't know
1203 use_bitmap_method
= TRUE
;
1205 else if (memDC
->m_selected
.GetDepth() == 1)
1207 /* we HAVE TO use the direct way for memory dcs
1208 that are bitmaps because XCopyArea doesn't cope
1209 with different bit depths */
1211 use_bitmap_method
= TRUE
;
1213 else if ((xsrc
== 0) && (ysrc
== 0) &&
1214 (width
== memDC
->m_selected
.GetWidth()) &&
1215 (height
== memDC
->m_selected
.GetHeight()))
1217 /* we SHOULD use the direct way if all of the bitmap
1218 in the memory dc is copied in which case XCopyArea
1219 wouldn't be able able to boost performace by reducing
1220 the area to be scaled */
1221 use_bitmap_method
= TRUE
;
1225 use_bitmap_method
= FALSE
;
1229 CalcBoundingBox( xdest
, ydest
);
1230 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1232 /* scale/translate size and position */
1233 wxCoord xx
= XLOG2DEV(xdest
);
1234 wxCoord yy
= YLOG2DEV(ydest
);
1236 wxCoord ww
= XLOG2DEVREL(width
);
1237 wxCoord hh
= YLOG2DEVREL(height
);
1239 /* compare to current clipping region */
1240 if (!m_currentClippingRegion
.IsNull())
1242 wxRegion
tmp( xx
,yy
,ww
,hh
);
1243 tmp
.Intersect( m_currentClippingRegion
);
1248 int old_logical_func
= m_logicalFunction
;
1249 SetLogicalFunction( logical_func
);
1251 if (use_bitmap_method
)
1253 /* scale/translate bitmap size */
1254 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1255 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1257 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1258 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1260 /* scale bitmap if required */
1261 wxBitmap use_bitmap
;
1263 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1265 wxImage image
= memDC
->m_selected
.ConvertToImage();
1266 image
= image
.Scale( bm_ww
, bm_hh
);
1269 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1271 use_bitmap
= wxBitmap(image
);
1275 use_bitmap
= memDC
->m_selected
;
1278 /* apply mask if any */
1279 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1280 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1282 if (useMask
&& mask
)
1284 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1285 #ifndef __WXGTK20__ // TODO fix crash
1286 if (!m_currentClippingRegion
.IsNull())
1289 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1290 GdkGC
*gc
= gdk_gc_new( new_mask
);
1292 gdk_gc_set_foreground( gc
, &col
);
1293 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1295 gdk_gc_set_background( gc
, &col
);
1297 gdk_gc_set_foreground( gc
, &col
);
1298 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1299 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1300 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1301 gdk_gc_set_stipple( gc
, mask
);
1302 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1309 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1311 gdk_gc_set_clip_mask( m_textGC
, mask
);
1312 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1317 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1319 gdk_gc_set_clip_mask( m_penGC
, mask
);
1320 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1323 gdk_bitmap_unref( new_mask
);
1326 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1327 drawing a mono-bitmap (XBitmap) we use the current text GC */
1330 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1332 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1334 /* remove mask again if any */
1335 if (useMask
&& mask
)
1339 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1340 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1341 if (!m_currentClippingRegion
.IsNull())
1342 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1346 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1347 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1348 if (!m_currentClippingRegion
.IsNull())
1349 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1353 else /* use_bitmap_method */
1355 if ((width
!= ww
) || (height
!= hh
))
1357 /* draw source window into a bitmap as we cannot scale
1358 a window in contrast to a bitmap. this would actually
1359 work with memory dcs as well, but we'd lose the mask
1360 information and waste one step in this process since
1361 a memory already has a bitmap. all this is slightly
1362 inefficient as we could take an XImage directly from
1363 an X window, but we'd then also have to care that
1364 the window is not outside the screen (in which case
1365 we'd get a BadMatch or what not).
1366 Is a double XGetImage and combined XGetPixel and
1367 XPutPixel really faster? I'm not sure. look at wxXt
1368 for a different implementation of the same problem. */
1370 wxBitmap
bitmap( width
, height
);
1372 /* copy including child window contents */
1373 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1374 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1376 xsrc
, ysrc
, width
, height
);
1377 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1380 wxImage image
= bitmap
.ConvertToImage();
1381 image
= image
.Scale( ww
, hh
);
1383 /* convert to bitmap */
1384 bitmap
= wxBitmap(image
);
1386 /* draw scaled bitmap */
1387 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1392 /* No scaling and not a memory dc with a mask either */
1394 /* copy including child window contents */
1395 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1396 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1398 xsrc
, ysrc
, width
, height
);
1399 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1403 SetLogicalFunction( old_logical_func
);
1407 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1409 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1411 if (!m_window
) return;
1413 if (text
.empty()) return;
1416 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1418 wxCHECK_RET( font
, wxT("invalid font") );
1422 wxCHECK_RET( m_context
, wxT("no Pango context") );
1429 // TODO: the layout engine should be abstracted at a higher level!
1430 PangoLayout
*layout
= pango_layout_new(m_context
);
1431 pango_layout_set_font_description(layout
, m_fontdesc
);
1434 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
1435 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1437 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( text
);
1438 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1439 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1445 pango_layout_get_pixel_size(layout
, &w
, &h
);
1450 gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout
);
1452 g_object_unref( G_OBJECT( layout
) );
1454 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1455 wxCoord height
= font
->ascent
+ font
->descent
;
1457 if ( m_backgroundMode
== wxSOLID
)
1459 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1460 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1461 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1463 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1465 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1466 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1467 properties (see wxXt implementation) */
1468 if (m_font
.GetUnderlined())
1470 wxCoord ul_y
= y
+ font
->ascent
;
1471 if (font
->descent
> 0) ul_y
++;
1472 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1474 #endif // GTK+ 2.0/1.x
1477 width
= wxCoord(width
/ m_scaleX
);
1478 height
= wxCoord(height
/ m_scaleY
);
1479 CalcBoundingBox (x
+ width
, y
+ height
);
1480 CalcBoundingBox (x
, y
);
1483 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1487 DrawText(text
, x
, y
);
1491 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1493 if (!m_window
) return;
1495 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1497 wxCHECK_RET( font
, wxT("invalid font") );
1499 // the size of the text
1500 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1501 wxCoord h
= font
->ascent
+ font
->descent
;
1503 // draw the string normally
1506 dc
.SelectObject(src
);
1507 dc
.SetFont(GetFont());
1508 dc
.SetBackground(*wxWHITE_BRUSH
);
1509 dc
.SetBrush(*wxBLACK_BRUSH
);
1511 dc
.DrawText(text
, 0, 0);
1512 dc
.SelectObject(wxNullBitmap
);
1514 // Calculate the size of the rotated bounding box.
1515 double rad
= DegToRad(angle
);
1516 double dx
= cos(rad
),
1519 // the rectngle vertices are counted clockwise with the first one being at
1520 // (0, 0) (or, rather, at (x, y))
1522 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1525 double x3
= x4
+ x2
,
1529 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1530 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1531 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1532 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1534 // prepare to blit-with-rotate the bitmap to the DC
1535 wxImage image
= src
.ConvertToImage();
1537 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1538 *colBack
= m_textBackgroundColour
.GetColor();
1540 bool textColSet
= TRUE
;
1542 unsigned char *data
= image
.GetData();
1544 // paint pixel by pixel
1545 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1547 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1549 // transform source coords to dest coords
1550 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1551 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1552 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1553 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1556 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1557 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1559 // change colour if needed
1560 if ( textPixel
!= textColSet
)
1562 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1565 textColSet
= textPixel
;
1568 // don't use DrawPoint() because it uses the current pen
1569 // colour, and we don't need it here
1570 gdk_draw_point( m_window
, m_textGC
,
1571 XLOG2DEV(x
) + dstX
, YLOG2DEV(y
) + dstY
);
1576 // it would be better to draw with non underlined font and draw the line
1577 // manually here (it would be more straight...)
1579 if ( m_font
.GetUnderlined() )
1581 gdk_draw_line( m_window
, m_textGC
,
1582 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1583 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1587 // restore the font colour
1588 gdk_gc_set_foreground( m_textGC
, colText
);
1590 // update the bounding box
1591 CalcBoundingBox(x
+ minX
, y
+ minY
);
1592 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1595 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1596 wxCoord
*width
, wxCoord
*height
,
1597 wxCoord
*descent
, wxCoord
*externalLeading
,
1598 wxFont
*theFont
) const
1600 if (string
.IsEmpty())
1602 if (width
) (*width
) = 0;
1603 if (height
) (*height
) = 0;
1608 // Create layout and set font description
1609 PangoLayout
*layout
= pango_layout_new(m_context
);
1611 pango_layout_set_font_description( layout
, theFont
->GetNativeFontInfo()->description
);
1613 pango_layout_set_font_description(layout
, m_fontdesc
);
1615 // Set layout's text
1617 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
1618 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1620 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( string
);
1621 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1622 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1627 pango_layout_get_pixel_size(layout
, &w
, &h
);
1629 if (width
) (*width
) = (wxCoord
) w
;
1630 if (height
) (*height
) = (wxCoord
) h
;
1633 // Do something about metrics here. TODO.
1636 if (externalLeading
) (*externalLeading
) = 0; // ??
1638 g_object_unref( G_OBJECT( layout
) );
1640 wxFont fontToUse
= m_font
;
1641 if (theFont
) fontToUse
= *theFont
;
1643 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1644 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1645 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1646 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1647 if (externalLeading
) (*externalLeading
) = 0; // ??
1651 wxCoord
wxWindowDC::GetCharWidth() const
1654 // There should be an easier way.
1655 PangoLayout
*layout
= pango_layout_new(m_context
);
1656 pango_layout_set_font_description(layout
, m_fontdesc
);
1657 pango_layout_set_text(layout
, "H", 1 );
1659 pango_layout_get_pixel_size(layout
, &w
, &h
);
1660 g_object_unref( G_OBJECT( layout
) );
1663 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1664 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1666 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1670 wxCoord
wxWindowDC::GetCharHeight() const
1673 // There should be an easier way.
1674 PangoLayout
*layout
= pango_layout_new(m_context
);
1675 pango_layout_set_font_description(layout
, m_fontdesc
);
1676 pango_layout_set_text(layout
, "H", 1 );
1678 pango_layout_get_pixel_size(layout
, &w
, &h
);
1679 g_object_unref( G_OBJECT( layout
) );
1682 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1683 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1685 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1689 void wxWindowDC::Clear()
1691 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1693 if (!m_window
) return;
1695 // VZ: the code below results in infinite recursion and crashes when
1696 // dc.Clear() is done from OnPaint() so I disable it for now.
1697 // I don't know what the correct fix is but Clear() surely should not
1698 // reenter OnPaint()!
1700 /* - we either are a memory dc or have a window as the
1701 owner. anything else shouldn't happen.
1702 - we don't use gdk_window_clear() as we don't set
1703 the window's background colour anymore. it is too
1704 much pain to keep the DC's and the window's back-
1705 ground colour in synch. */
1716 GetSize( &width
, &height
);
1717 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1722 GetSize( &width
, &height
);
1723 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1727 void wxWindowDC::SetFont( const wxFont
&font
)
1729 // It is common practice to set the font to wxNullFont, so
1730 // don't consider it to be an error
1731 // wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") );
1737 m_fontdesc
= m_font
.GetNativeFontInfo()->description
;
1741 if (m_font
.GetNoAntiAliasing())
1742 m_context
= m_owner
->GtkGetPangoX11Context();
1744 m_context
= m_owner
->GtkGetPangoDefaultContext();
1750 void wxWindowDC::SetPen( const wxPen
&pen
)
1752 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1754 if (m_pen
== pen
) return;
1758 if (!m_pen
.Ok()) return;
1760 if (!m_window
) return;
1762 gint width
= m_pen
.GetWidth();
1765 // CMB: if width is non-zero scale it with the dc
1770 // X doesn't allow different width in x and y and so we take
1773 ( fabs((double) XLOG2DEVREL(width
)) +
1774 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1778 static const wxGTKDash dotted
[] = {1, 1};
1779 static const wxGTKDash short_dashed
[] = {2, 2};
1780 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1781 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1783 // We express dash pattern in pen width unit, so we are
1784 // independent of zoom factor and so on...
1786 const wxGTKDash
*req_dash
;
1788 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1789 switch (m_pen
.GetStyle())
1793 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1794 req_nb_dash
= m_pen
.GetDashCount();
1795 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1800 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1807 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1809 req_dash
= wxCoord_dashed
;
1814 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1816 req_dash
= short_dashed
;
1821 // lineStyle = GDK_LINE_DOUBLE_DASH;
1822 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1824 req_dash
= dotted_dashed
;
1829 case wxSTIPPLE_MASK_OPAQUE
:
1834 lineStyle
= GDK_LINE_SOLID
;
1835 req_dash
= (wxGTKDash
*)NULL
;
1841 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1842 if (req_dash
&& req_nb_dash
)
1844 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1847 for (int i
= 0; i
< req_nb_dash
; i
++)
1848 real_req_dash
[i
] = req_dash
[i
] * width
;
1849 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1850 delete[] real_req_dash
;
1854 // No Memory. We use non-scaled dash pattern...
1855 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1858 #endif // GTK+ > 1.0
1860 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1861 switch (m_pen
.GetCap())
1863 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1864 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1871 capStyle
= GDK_CAP_NOT_LAST
;
1875 capStyle
= GDK_CAP_ROUND
;
1881 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1882 switch (m_pen
.GetJoin())
1884 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1885 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1887 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1890 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1892 m_pen
.GetColour().CalcPixel( m_cmap
);
1893 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1896 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1898 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1900 if (m_brush
== brush
) return;
1904 if (!m_brush
.Ok()) return;
1906 if (!m_window
) return;
1908 m_brush
.GetColour().CalcPixel( m_cmap
);
1909 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1911 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1913 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1915 if (m_brush
.GetStipple()->GetPixmap())
1917 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1918 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1922 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1923 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1927 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1929 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1930 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1933 if (IS_HATCH(m_brush
.GetStyle()))
1935 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1936 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1937 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1941 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1943 /* CMB 21/7/98: Added SetBackground. Sets background brush
1944 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1946 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1948 if (m_backgroundBrush
== brush
) return;
1950 m_backgroundBrush
= brush
;
1952 if (!m_backgroundBrush
.Ok()) return;
1954 if (!m_window
) return;
1956 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1957 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1958 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1959 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1960 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1962 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1964 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1966 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1968 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1969 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1973 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1974 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1978 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1980 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1981 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1982 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1986 void wxWindowDC::SetLogicalFunction( int function
)
1988 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1990 if (m_logicalFunction
== function
)
1993 // VZ: shouldn't this be a CHECK?
2000 case wxXOR
: mode
= GDK_XOR
; break;
2001 case wxINVERT
: mode
= GDK_INVERT
; break;
2002 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
2003 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
2004 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
2005 case wxCLEAR
: mode
= GDK_CLEAR
; break;
2006 case wxSET
: mode
= GDK_SET
; break;
2007 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
2008 case wxAND
: mode
= GDK_AND
; break;
2009 case wxOR
: mode
= GDK_OR
; break;
2010 case wxEQUIV
: mode
= GDK_EQUIV
; break;
2011 case wxNAND
: mode
= GDK_NAND
; break;
2012 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
2013 case wxCOPY
: mode
= GDK_COPY
; break;
2014 case wxNO_OP
: mode
= GDK_NOOP
; break;
2015 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
2017 // unsupported by GTK
2018 case wxNOR
: mode
= GDK_COPY
; break;
2019 #endif // GTK+ > 1.0
2021 wxFAIL_MSG( wxT("unsupported logical function") );
2025 m_logicalFunction
= function
;
2027 gdk_gc_set_function( m_penGC
, mode
);
2028 gdk_gc_set_function( m_brushGC
, mode
);
2030 // to stay compatible with wxMSW, we don't apply ROPs to the text
2031 // operations (i.e. DrawText/DrawRotatedText).
2032 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2033 gdk_gc_set_function( m_textGC
, mode
);
2036 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2038 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2040 // don't set m_textForegroundColour to an invalid colour as we'd crash
2041 // later then (we use m_textForegroundColour.GetColor() without checking
2043 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
2046 m_textForegroundColour
= col
;
2050 m_textForegroundColour
.CalcPixel( m_cmap
);
2051 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
2055 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2057 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2060 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
2063 m_textBackgroundColour
= col
;
2067 m_textBackgroundColour
.CalcPixel( m_cmap
);
2068 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
2072 void wxWindowDC::SetBackgroundMode( int mode
)
2074 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2076 m_backgroundMode
= mode
;
2078 if (!m_window
) return;
2080 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2081 // transparent/solid background mode
2083 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2085 gdk_gc_set_fill( m_brushGC
,
2086 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2090 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2092 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2095 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2097 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2099 if (!m_window
) return;
2102 rect
.x
= XLOG2DEV(x
);
2103 rect
.y
= YLOG2DEV(y
);
2104 rect
.width
= XLOG2DEVREL(width
);
2105 rect
.height
= YLOG2DEVREL(height
);
2107 if (!m_currentClippingRegion
.IsNull())
2108 m_currentClippingRegion
.Intersect( rect
);
2110 m_currentClippingRegion
.Union( rect
);
2112 #if USE_PAINT_REGION
2113 if (!m_paintClippingRegion
.IsNull())
2114 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2117 wxCoord xx
, yy
, ww
, hh
;
2118 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2119 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2121 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2122 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2123 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2124 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2127 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2129 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2133 DestroyClippingRegion();
2137 if (!m_window
) return;
2139 if (!m_currentClippingRegion
.IsNull())
2140 m_currentClippingRegion
.Intersect( region
);
2142 m_currentClippingRegion
.Union( region
);
2144 #if USE_PAINT_REGION
2145 if (!m_paintClippingRegion
.IsNull())
2146 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2149 wxCoord xx
, yy
, ww
, hh
;
2150 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2151 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2153 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2154 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2155 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2156 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2159 void wxWindowDC::DestroyClippingRegion()
2161 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2163 wxDC::DestroyClippingRegion();
2165 m_currentClippingRegion
.Clear();
2167 #if USE_PAINT_REGION
2168 if (!m_paintClippingRegion
.IsEmpty())
2169 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2172 if (!m_window
) return;
2174 if (m_currentClippingRegion
.IsEmpty())
2176 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2177 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2178 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2179 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2183 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2184 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2185 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2186 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2190 void wxWindowDC::Destroy()
2192 if (m_penGC
) wxFreePoolGC( m_penGC
);
2193 m_penGC
= (GdkGC
*) NULL
;
2194 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2195 m_brushGC
= (GdkGC
*) NULL
;
2196 if (m_textGC
) wxFreePoolGC( m_textGC
);
2197 m_textGC
= (GdkGC
*) NULL
;
2198 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2199 m_bgGC
= (GdkGC
*) NULL
;
2202 void wxWindowDC::ComputeScaleAndOrigin()
2204 /* CMB: copy scale to see if it changes */
2205 double origScaleX
= m_scaleX
;
2206 double origScaleY
= m_scaleY
;
2208 wxDC::ComputeScaleAndOrigin();
2210 /* CMB: if scale has changed call SetPen to recalulate the line width */
2211 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2214 /* this is a bit artificial, but we need to force wxDC to think
2215 the pen has changed */
2222 // Resolution in pixels per logical inch
2223 wxSize
wxWindowDC::GetPPI() const
2225 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2228 int wxWindowDC::GetDepth() const
2230 wxFAIL_MSG(wxT("not implemented"));
2236 //-----------------------------------------------------------------------------
2238 //-----------------------------------------------------------------------------
2240 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2242 wxPaintDC::wxPaintDC( wxWindow
*win
)
2245 #if USE_PAINT_REGION
2246 if (!win
->m_clipPaintRegion
)
2249 m_paintClippingRegion
= win
->GetUpdateRegion();
2250 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2253 m_paintClippingRegion
= win
->GetUpdateRegion();
2254 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2257 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2259 gdk_gc_set_clip_region( m_penGC
, region
);
2260 gdk_gc_set_clip_region( m_brushGC
, region
);
2261 gdk_gc_set_clip_region( m_textGC
, region
);
2262 gdk_gc_set_clip_region( m_bgGC
, region
);
2265 #endif // USE_PAINT_REGION
2268 //-----------------------------------------------------------------------------
2270 //-----------------------------------------------------------------------------
2272 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2274 wxClientDC::wxClientDC( wxWindow
*win
)
2277 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2279 #ifdef __WXUNIVERSAL__
2280 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2281 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2282 wxSize size
= win
->GetClientSize();
2283 SetClippingRegion(wxPoint(0, 0), size
);
2284 #endif // __WXUNIVERSAL__
2287 void wxClientDC::DoGetSize(int *width
, int *height
) const
2289 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2291 m_owner
->GetClientSize( width
, height
);
2294 // ----------------------------------------------------------------------------
2296 // ----------------------------------------------------------------------------
2298 class wxDCModule
: public wxModule
2305 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2308 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2310 bool wxDCModule::OnInit()
2316 void wxDCModule::OnExit()