]>
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
);
400 m_context
= gdk_pango_context_get();
401 m_fontdesc
= pango_context_get_font_description(m_context
);
405 /* background colour */
406 m_backgroundBrush
= *wxWHITE_BRUSH
;
407 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
408 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
411 m_textForegroundColour
.CalcPixel( m_cmap
);
412 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
414 m_textBackgroundColour
.CalcPixel( m_cmap
);
415 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
417 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
420 m_pen
.GetColour().CalcPixel( m_cmap
);
421 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
422 gdk_gc_set_background( m_penGC
, bg_col
);
424 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
427 m_brush
.GetColour().CalcPixel( m_cmap
);
428 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
429 gdk_gc_set_background( m_brushGC
, bg_col
);
431 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
434 gdk_gc_set_background( m_bgGC
, bg_col
);
435 gdk_gc_set_foreground( m_bgGC
, bg_col
);
437 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
440 gdk_gc_set_function( m_textGC
, GDK_COPY
);
441 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
442 gdk_gc_set_function( m_penGC
, GDK_COPY
);
445 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
446 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
447 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
448 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
452 hatch_bitmap
= hatches
;
453 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
454 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
455 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
456 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
457 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
458 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
462 void wxWindowDC::DoGetSize( int* width
, int* height
) const
464 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
466 m_owner
->GetSize(width
, height
);
469 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
470 const wxColour
& col
, int style
);
472 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
473 const wxColour
& col
, int style
)
475 return wxDoFloodFill(this, x
, y
, col
, style
);
478 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
480 // Generic (and therefore rather inefficient) method.
481 // Could be improved.
483 wxBitmap
bitmap(1, 1);
484 memdc
.SelectObject(bitmap
);
485 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
486 memdc
.SelectObject(wxNullBitmap
);
488 wxImage image
= bitmap
.ConvertToImage();
489 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
493 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
495 wxCHECK_RET( Ok(), wxT("invalid window dc") );
497 if (m_pen
.GetStyle() != wxTRANSPARENT
)
500 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
502 CalcBoundingBox(x1
, y1
);
503 CalcBoundingBox(x2
, y2
);
507 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
509 wxCHECK_RET( Ok(), wxT("invalid window dc") );
511 if (m_pen
.GetStyle() != wxTRANSPARENT
)
516 wxCoord xx
= XLOG2DEV(x
);
517 wxCoord yy
= YLOG2DEV(y
);
520 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
521 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
526 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
527 wxCoord xc
, wxCoord yc
)
529 wxCHECK_RET( Ok(), wxT("invalid window dc") );
531 wxCoord xx1
= XLOG2DEV(x1
);
532 wxCoord yy1
= YLOG2DEV(y1
);
533 wxCoord xx2
= XLOG2DEV(x2
);
534 wxCoord yy2
= YLOG2DEV(y2
);
535 wxCoord xxc
= XLOG2DEV(xc
);
536 wxCoord yyc
= YLOG2DEV(yc
);
537 double dx
= xx1
- xxc
;
538 double dy
= yy1
- yyc
;
539 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
540 wxCoord r
= (wxCoord
)radius
;
541 double radius1
, radius2
;
543 if (xx1
== xx2
&& yy1
== yy2
)
551 radius1
= radius2
= 0.0;
555 radius1
= (xx1
- xxc
== 0) ?
556 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
557 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
558 radius2
= (xx2
- xxc
== 0) ?
559 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
560 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
562 wxCoord alpha1
= wxCoord(radius1
* 64.0);
563 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
564 while (alpha2
<= 0) alpha2
+= 360*64;
565 while (alpha1
> 360*64) alpha1
-= 360*64;
569 if (m_brush
.GetStyle() != wxTRANSPARENT
)
571 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
573 gdk_gc_set_ts_origin( m_textGC
,
574 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
575 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
576 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
577 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
579 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
581 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
582 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
583 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
585 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
587 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
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 );
591 if (m_brush
.GetStyle() == wxSTIPPLE
)
593 gdk_gc_set_ts_origin( m_brushGC
,
594 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
595 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
596 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
597 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
601 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
605 if (m_pen
.GetStyle() != wxTRANSPARENT
)
607 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
609 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
610 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
614 CalcBoundingBox (x1
, y1
);
615 CalcBoundingBox (x2
, y2
);
618 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
620 wxCHECK_RET( Ok(), wxT("invalid window dc") );
622 wxCoord xx
= XLOG2DEV(x
);
623 wxCoord yy
= YLOG2DEV(y
);
624 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
625 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
627 // CMB: handle -ve width and/or height
628 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
629 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
633 wxCoord start
= wxCoord(sa
* 64.0);
634 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
636 if (m_brush
.GetStyle() != wxTRANSPARENT
)
638 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
640 gdk_gc_set_ts_origin( m_textGC
,
641 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
642 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
643 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
644 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
646 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
648 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
649 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
650 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
652 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
654 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
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 );
658 if (m_brush
.GetStyle() == wxSTIPPLE
)
660 gdk_gc_set_ts_origin( m_brushGC
,
661 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
662 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
663 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
664 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
668 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
672 if (m_pen
.GetStyle() != wxTRANSPARENT
)
673 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
676 CalcBoundingBox (x
, y
);
677 CalcBoundingBox (x
+ width
, y
+ height
);
680 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
682 wxCHECK_RET( Ok(), wxT("invalid window dc") );
684 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
685 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
687 CalcBoundingBox (x
, y
);
690 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
692 wxCHECK_RET( Ok(), wxT("invalid window dc") );
694 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
697 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
699 for (int i
= 0; i
< n
-1; i
++)
701 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
702 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
703 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
704 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
707 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
709 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
713 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
715 wxCHECK_RET( Ok(), wxT("invalid window dc") );
719 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
721 for (i
= 0 ; i
< n
; i
++)
723 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
724 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
726 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
731 if (m_brush
.GetStyle() != wxTRANSPARENT
)
733 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
735 gdk_gc_set_ts_origin( m_textGC
,
736 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
737 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
738 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
739 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
741 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
743 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
744 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
745 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
747 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
749 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
750 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
751 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
753 if (m_brush
.GetStyle() == wxSTIPPLE
)
755 gdk_gc_set_ts_origin( m_brushGC
,
756 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
757 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
758 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
759 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
763 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
767 if (m_pen
.GetStyle() != wxTRANSPARENT
)
769 for (i
= 0 ; i
< n
; i
++)
771 gdk_draw_line( m_window
, m_penGC
,
774 gdkpoints
[(i
+1)%n
].x
,
775 gdkpoints
[(i
+1)%n
].y
);
783 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
785 wxCHECK_RET( Ok(), wxT("invalid window dc") );
787 wxCoord xx
= XLOG2DEV(x
);
788 wxCoord yy
= YLOG2DEV(y
);
789 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
790 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
792 // CMB: draw nothing if transformed w or h is 0
793 if (ww
== 0 || hh
== 0) return;
795 // CMB: handle -ve width and/or height
796 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
797 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
801 if (m_brush
.GetStyle() != wxTRANSPARENT
)
803 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
805 gdk_gc_set_ts_origin( m_textGC
,
806 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
807 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
808 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
809 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
811 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
813 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
814 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
815 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
817 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
819 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
820 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
821 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
823 if (m_brush
.GetStyle() == wxSTIPPLE
)
825 gdk_gc_set_ts_origin( m_brushGC
,
826 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
827 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
828 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
829 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
833 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
837 if (m_pen
.GetStyle() != wxTRANSPARENT
)
838 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
841 CalcBoundingBox( x
, y
);
842 CalcBoundingBox( x
+ width
, y
+ height
);
845 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
847 wxCHECK_RET( Ok(), wxT("invalid window dc") );
849 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
851 wxCoord xx
= XLOG2DEV(x
);
852 wxCoord yy
= YLOG2DEV(y
);
853 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
854 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
855 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
857 // CMB: handle -ve width and/or height
858 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
859 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
861 // CMB: if radius is zero use DrawRectangle() instead to avoid
862 // X drawing errors with small radii
865 DrawRectangle( x
, y
, width
, height
);
869 // CMB: draw nothing if transformed w or h is 0
870 if (ww
== 0 || hh
== 0) return;
872 // CMB: adjust size if outline is drawn otherwise the result is
873 // 1 pixel too wide and high
874 if (m_pen
.GetStyle() != wxTRANSPARENT
)
882 // CMB: ensure dd is not larger than rectangle otherwise we
883 // get an hour glass shape
885 if (dd
> ww
) dd
= ww
;
886 if (dd
> hh
) dd
= hh
;
889 if (m_brush
.GetStyle() != wxTRANSPARENT
)
891 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
893 gdk_gc_set_ts_origin( m_textGC
,
894 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
895 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
896 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
897 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
898 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
899 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
900 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
901 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
902 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
904 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
906 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
907 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
908 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
909 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
910 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
911 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
912 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
913 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
915 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
917 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
918 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
919 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
920 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
921 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
922 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
923 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
924 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
926 if (m_brush
.GetStyle() == wxSTIPPLE
)
928 gdk_gc_set_ts_origin( m_brushGC
,
929 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
930 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
931 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
932 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
933 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
934 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
935 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
936 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
937 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
941 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
942 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
943 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
944 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
945 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
946 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
950 if (m_pen
.GetStyle() != wxTRANSPARENT
)
952 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
953 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
954 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
955 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
956 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
957 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
958 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
959 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
963 // this ignores the radius
964 CalcBoundingBox( x
, y
);
965 CalcBoundingBox( x
+ width
, y
+ height
);
968 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
970 wxCHECK_RET( Ok(), wxT("invalid window dc") );
972 wxCoord xx
= XLOG2DEV(x
);
973 wxCoord yy
= YLOG2DEV(y
);
974 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
975 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
977 // CMB: handle -ve width and/or height
978 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
979 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
983 if (m_brush
.GetStyle() != wxTRANSPARENT
)
985 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
987 gdk_gc_set_ts_origin( m_textGC
,
988 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
989 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
990 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
991 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
993 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
995 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
996 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
997 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
999 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
1001 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
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 );
1005 if (m_brush
.GetStyle() == wxSTIPPLE
)
1007 gdk_gc_set_ts_origin( m_brushGC
,
1008 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1009 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1010 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1011 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1015 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1019 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1020 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1023 CalcBoundingBox( x
, y
);
1024 CalcBoundingBox( x
+ width
, y
+ height
);
1027 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1029 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1030 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1033 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1034 wxCoord x
, wxCoord y
,
1037 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1039 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1041 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1043 /* scale/translate size and position */
1044 int xx
= XLOG2DEV(x
);
1045 int yy
= YLOG2DEV(y
);
1047 int w
= bitmap
.GetWidth();
1048 int h
= bitmap
.GetHeight();
1050 CalcBoundingBox( x
, y
);
1051 CalcBoundingBox( x
+ w
, y
+ h
);
1053 if (!m_window
) return;
1055 int ww
= XLOG2DEVREL(w
);
1056 int hh
= YLOG2DEVREL(h
);
1058 /* compare to current clipping region */
1059 if (!m_currentClippingRegion
.IsNull())
1061 wxRegion
tmp( xx
,yy
,ww
,hh
);
1062 tmp
.Intersect( m_currentClippingRegion
);
1067 /* scale bitmap if required */
1068 wxBitmap use_bitmap
;
1069 if ((w
!= ww
) || (h
!= hh
))
1071 wxImage image
= bitmap
.ConvertToImage();
1072 image
.Rescale( ww
, hh
);
1074 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1076 use_bitmap
= wxBitmap(image
);
1080 use_bitmap
= bitmap
;
1083 /* apply mask if any */
1084 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1085 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1087 if (useMask
&& mask
)
1089 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1090 #ifndef __WXGTK20__ // TODO fix crash
1091 if (!m_currentClippingRegion
.IsNull())
1094 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1095 GdkGC
*gc
= gdk_gc_new( new_mask
);
1097 gdk_gc_set_foreground( gc
, &col
);
1098 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1100 gdk_gc_set_background( gc
, &col
);
1102 gdk_gc_set_foreground( gc
, &col
);
1103 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1104 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1105 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1106 gdk_gc_set_stipple( gc
, mask
);
1107 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1114 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1116 gdk_gc_set_clip_mask( m_textGC
, mask
);
1117 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1122 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1124 gdk_gc_set_clip_mask( m_penGC
, mask
);
1125 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1129 gdk_bitmap_unref( new_mask
);
1132 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1133 drawing a mono-bitmap (XBitmap) we use the current text GC */
1135 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1137 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1139 /* remove mask again if any */
1140 if (useMask
&& mask
)
1144 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1145 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1146 if (!m_currentClippingRegion
.IsNull())
1147 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1151 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1152 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1153 if (!m_currentClippingRegion
.IsNull())
1154 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1159 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1160 wxCoord width
, wxCoord height
,
1162 wxCoord xsrc
, wxCoord ysrc
,
1165 wxCoord xsrcMask
, wxCoord ysrcMask
)
1167 /* this is the nth try to get this utterly useless function to
1168 work. it now completely ignores the scaling or translation
1169 of the source dc, but scales correctly on the target dc and
1170 knows about possible mask information in a memory dc. */
1172 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1174 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1176 if (!m_window
) return FALSE
;
1179 // transform the source DC coords to the device ones
1180 xsrc
= source
->XLOG2DEV(xsrc
);
1181 ysrc
= source
->YLOG2DEV(ysrc
);
1184 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1185 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1187 bool use_bitmap_method
= FALSE
;
1188 bool is_mono
= FALSE
;
1190 /* TODO: use the mask origin when drawing transparently */
1191 if (xsrcMask
== -1 && ysrcMask
== -1)
1193 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1196 if (srcDC
->m_isMemDC
)
1198 if (!memDC
->m_selected
.Ok()) return FALSE
;
1200 /* we use the "XCopyArea" way to copy a memory dc into
1201 y different window if the memory dc BOTH
1202 a) doesn't have any mask or its mask isn't used
1206 if (useMask
&& (memDC
->m_selected
.GetMask()))
1208 /* we HAVE TO use the direct way for memory dcs
1209 that have mask since the XCopyArea doesn't know
1211 use_bitmap_method
= TRUE
;
1213 else if (memDC
->m_selected
.GetDepth() == 1)
1215 /* we HAVE TO use the direct way for memory dcs
1216 that are bitmaps because XCopyArea doesn't cope
1217 with different bit depths */
1219 use_bitmap_method
= TRUE
;
1221 else if ((xsrc
== 0) && (ysrc
== 0) &&
1222 (width
== memDC
->m_selected
.GetWidth()) &&
1223 (height
== memDC
->m_selected
.GetHeight()))
1225 /* we SHOULD use the direct way if all of the bitmap
1226 in the memory dc is copied in which case XCopyArea
1227 wouldn't be able able to boost performace by reducing
1228 the area to be scaled */
1229 use_bitmap_method
= TRUE
;
1233 use_bitmap_method
= FALSE
;
1237 CalcBoundingBox( xdest
, ydest
);
1238 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1240 /* scale/translate size and position */
1241 wxCoord xx
= XLOG2DEV(xdest
);
1242 wxCoord yy
= YLOG2DEV(ydest
);
1244 wxCoord ww
= XLOG2DEVREL(width
);
1245 wxCoord hh
= YLOG2DEVREL(height
);
1247 /* compare to current clipping region */
1248 if (!m_currentClippingRegion
.IsNull())
1250 wxRegion
tmp( xx
,yy
,ww
,hh
);
1251 tmp
.Intersect( m_currentClippingRegion
);
1256 int old_logical_func
= m_logicalFunction
;
1257 SetLogicalFunction( logical_func
);
1259 if (use_bitmap_method
)
1261 /* scale/translate bitmap size */
1262 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1263 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1265 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1266 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1268 /* scale bitmap if required */
1269 wxBitmap use_bitmap
;
1271 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1273 wxImage image
= memDC
->m_selected
.ConvertToImage();
1274 image
= image
.Scale( bm_ww
, bm_hh
);
1277 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1279 use_bitmap
= wxBitmap(image
);
1283 use_bitmap
= memDC
->m_selected
;
1286 /* apply mask if any */
1287 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1288 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1290 if (useMask
&& mask
)
1292 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1293 #ifndef __WXGTK20__ // TODO fix crash
1294 if (!m_currentClippingRegion
.IsNull())
1297 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1298 GdkGC
*gc
= gdk_gc_new( new_mask
);
1300 gdk_gc_set_foreground( gc
, &col
);
1301 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1303 gdk_gc_set_background( gc
, &col
);
1305 gdk_gc_set_foreground( gc
, &col
);
1306 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1307 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1308 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1309 gdk_gc_set_stipple( gc
, mask
);
1310 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1317 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1319 gdk_gc_set_clip_mask( m_textGC
, mask
);
1320 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1325 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1327 gdk_gc_set_clip_mask( m_penGC
, mask
);
1328 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1331 gdk_bitmap_unref( new_mask
);
1334 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1335 drawing a mono-bitmap (XBitmap) we use the current text GC */
1338 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1340 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1342 /* remove mask again if any */
1343 if (useMask
&& mask
)
1347 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1348 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1349 if (!m_currentClippingRegion
.IsNull())
1350 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1354 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1355 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1356 if (!m_currentClippingRegion
.IsNull())
1357 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1361 else /* use_bitmap_method */
1363 if ((width
!= ww
) || (height
!= hh
))
1365 /* draw source window into a bitmap as we cannot scale
1366 a window in contrast to a bitmap. this would actually
1367 work with memory dcs as well, but we'd lose the mask
1368 information and waste one step in this process since
1369 a memory already has a bitmap. all this is slightly
1370 inefficient as we could take an XImage directly from
1371 an X window, but we'd then also have to care that
1372 the window is not outside the screen (in which case
1373 we'd get a BadMatch or what not).
1374 Is a double XGetImage and combined XGetPixel and
1375 XPutPixel really faster? I'm not sure. look at wxXt
1376 for a different implementation of the same problem. */
1378 wxBitmap
bitmap( width
, height
);
1380 /* copy including child window contents */
1381 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1382 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1384 xsrc
, ysrc
, width
, height
);
1385 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1388 wxImage image
= bitmap
.ConvertToImage();
1389 image
= image
.Scale( ww
, hh
);
1391 /* convert to bitmap */
1392 bitmap
= wxBitmap(image
);
1394 /* draw scaled bitmap */
1395 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1400 /* No scaling and not a memory dc with a mask either */
1402 /* copy including child window contents */
1403 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1404 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1406 xsrc
, ysrc
, width
, height
);
1407 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1411 SetLogicalFunction( old_logical_func
);
1415 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1417 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1419 if (!m_window
) return;
1421 if (text
.empty()) return;
1424 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1426 wxCHECK_RET( font
, wxT("invalid font") );
1430 wxCHECK_RET( m_context
, wxT("no Pango context") );
1437 // TODO: the layout engine should be abstracted at a higher level!
1438 PangoLayout
*layout
= pango_layout_new(m_context
);
1439 pango_layout_set_font_description(layout
, m_fontdesc
);
1442 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
1443 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1445 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( text
);
1446 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1447 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1453 pango_layout_get_pixel_size(layout
, &w
, &h
);
1458 gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout
);
1460 g_object_unref( G_OBJECT( layout
) );
1462 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1463 wxCoord height
= font
->ascent
+ font
->descent
;
1465 if ( m_backgroundMode
== wxSOLID
)
1467 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1468 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1469 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1471 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1473 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1474 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1475 properties (see wxXt implementation) */
1476 if (m_font
.GetUnderlined())
1478 wxCoord ul_y
= y
+ font
->ascent
;
1479 if (font
->descent
> 0) ul_y
++;
1480 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1482 #endif // GTK+ 2.0/1.x
1485 width
= wxCoord(width
/ m_scaleX
);
1486 height
= wxCoord(height
/ m_scaleY
);
1487 CalcBoundingBox (x
+ width
, y
+ height
);
1488 CalcBoundingBox (x
, y
);
1491 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1495 DrawText(text
, x
, y
);
1499 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1501 if (!m_window
) return;
1504 // implement later without GdkFont for GTK 2.0
1507 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1509 wxCHECK_RET( font
, wxT("invalid font") );
1511 // the size of the text
1512 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1513 wxCoord h
= font
->ascent
+ font
->descent
;
1515 // draw the string normally
1518 dc
.SelectObject(src
);
1519 dc
.SetFont(GetFont());
1520 dc
.SetBackground(*wxWHITE_BRUSH
);
1521 dc
.SetBrush(*wxBLACK_BRUSH
);
1523 dc
.DrawText(text
, 0, 0);
1524 dc
.SelectObject(wxNullBitmap
);
1526 // Calculate the size of the rotated bounding box.
1527 double rad
= DegToRad(angle
);
1528 double dx
= cos(rad
),
1531 // the rectngle vertices are counted clockwise with the first one being at
1532 // (0, 0) (or, rather, at (x, y))
1534 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1537 double x3
= x4
+ x2
,
1541 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1542 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1543 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1544 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1546 // prepare to blit-with-rotate the bitmap to the DC
1547 wxImage image
= src
.ConvertToImage();
1549 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1550 *colBack
= m_textBackgroundColour
.GetColor();
1552 bool textColSet
= TRUE
;
1554 unsigned char *data
= image
.GetData();
1556 // paint pixel by pixel
1557 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1559 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1561 // transform source coords to dest coords
1562 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1563 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1564 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1565 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1568 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1569 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1571 // change colour if needed
1572 if ( textPixel
!= textColSet
)
1574 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1577 textColSet
= textPixel
;
1580 // don't use DrawPoint() because it uses the current pen
1581 // colour, and we don't need it here
1582 gdk_draw_point( m_window
, m_textGC
,
1583 XLOG2DEV(x
) + dstX
, YLOG2DEV(y
) + dstY
);
1588 // it would be better to draw with non underlined font and draw the line
1589 // manually here (it would be more straight...)
1591 if ( m_font
.GetUnderlined() )
1593 gdk_draw_line( m_window
, m_textGC
,
1594 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1595 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1599 // restore the font colour
1600 gdk_gc_set_foreground( m_textGC
, colText
);
1602 // update the bounding box
1603 CalcBoundingBox(x
+ minX
, y
+ minY
);
1604 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1607 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1608 wxCoord
*width
, wxCoord
*height
,
1609 wxCoord
*descent
, wxCoord
*externalLeading
,
1610 wxFont
*theFont
) const
1612 if (string
.IsEmpty())
1614 if (width
) (*width
) = 0;
1615 if (height
) (*height
) = 0;
1620 // Create layout and set font description
1621 PangoLayout
*layout
= pango_layout_new(m_context
);
1623 pango_layout_set_font_description( layout
, theFont
->GetNativeFontInfo()->description
);
1625 pango_layout_set_font_description(layout
, m_fontdesc
);
1627 // Set layout's text
1629 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
1630 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1632 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( string
);
1633 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1634 pango_layout_set_text(layout
, (const char*) data
, strlen( (const char*) data
));
1639 pango_layout_get_pixel_size(layout
, &w
, &h
);
1641 if (width
) (*width
) = (wxCoord
) w
;
1642 if (height
) (*height
) = (wxCoord
) h
;
1645 // Do something about metrics here. TODO.
1648 if (externalLeading
) (*externalLeading
) = 0; // ??
1650 g_object_unref( G_OBJECT( layout
) );
1652 wxFont fontToUse
= m_font
;
1653 if (theFont
) fontToUse
= *theFont
;
1655 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1656 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1657 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1658 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1659 if (externalLeading
) (*externalLeading
) = 0; // ??
1663 wxCoord
wxWindowDC::GetCharWidth() const
1666 // There should be an easier way.
1667 PangoLayout
*layout
= pango_layout_new(m_context
);
1668 pango_layout_set_font_description(layout
, m_fontdesc
);
1669 pango_layout_set_text(layout
, "H", 1 );
1671 pango_layout_get_pixel_size(layout
, &w
, &h
);
1672 g_object_unref( G_OBJECT( layout
) );
1675 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1676 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1678 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1682 wxCoord
wxWindowDC::GetCharHeight() const
1685 // There should be an easier way.
1686 PangoLayout
*layout
= pango_layout_new(m_context
);
1687 pango_layout_set_font_description(layout
, m_fontdesc
);
1688 pango_layout_set_text(layout
, "H", 1 );
1690 pango_layout_get_pixel_size(layout
, &w
, &h
);
1691 g_object_unref( G_OBJECT( layout
) );
1694 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1695 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1697 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1701 void wxWindowDC::Clear()
1703 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1705 if (!m_window
) return;
1707 // VZ: the code below results in infinite recursion and crashes when
1708 // dc.Clear() is done from OnPaint() so I disable it for now.
1709 // I don't know what the correct fix is but Clear() surely should not
1710 // reenter OnPaint()!
1712 /* - we either are a memory dc or have a window as the
1713 owner. anything else shouldn't happen.
1714 - we don't use gdk_window_clear() as we don't set
1715 the window's background colour anymore. it is too
1716 much pain to keep the DC's and the window's back-
1717 ground colour in synch. */
1728 GetSize( &width
, &height
);
1729 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1734 GetSize( &width
, &height
);
1735 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1739 void wxWindowDC::SetFont( const wxFont
&font
)
1741 // It is common practice to set the font to wxNullFont, so
1742 // don't consider it to be an error
1743 // wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") );
1749 m_fontdesc
= m_font
.GetNativeFontInfo()->description
;
1753 if (m_font
.GetNoAntiAliasing())
1754 m_context
= m_owner
->GtkGetPangoX11Context();
1756 m_context
= m_owner
->GtkGetPangoDefaultContext();
1762 void wxWindowDC::SetPen( const wxPen
&pen
)
1764 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1766 if (m_pen
== pen
) return;
1770 if (!m_pen
.Ok()) return;
1772 if (!m_window
) return;
1774 gint width
= m_pen
.GetWidth();
1777 // CMB: if width is non-zero scale it with the dc
1782 // X doesn't allow different width in x and y and so we take
1785 ( fabs((double) XLOG2DEVREL(width
)) +
1786 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1790 static const wxGTKDash dotted
[] = {1, 1};
1791 static const wxGTKDash short_dashed
[] = {2, 2};
1792 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1793 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1795 // We express dash pattern in pen width unit, so we are
1796 // independent of zoom factor and so on...
1798 const wxGTKDash
*req_dash
;
1800 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1801 switch (m_pen
.GetStyle())
1805 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1806 req_nb_dash
= m_pen
.GetDashCount();
1807 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1812 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1819 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1821 req_dash
= wxCoord_dashed
;
1826 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1828 req_dash
= short_dashed
;
1833 // lineStyle = GDK_LINE_DOUBLE_DASH;
1834 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1836 req_dash
= dotted_dashed
;
1841 case wxSTIPPLE_MASK_OPAQUE
:
1846 lineStyle
= GDK_LINE_SOLID
;
1847 req_dash
= (wxGTKDash
*)NULL
;
1853 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1854 if (req_dash
&& req_nb_dash
)
1856 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1859 for (int i
= 0; i
< req_nb_dash
; i
++)
1860 real_req_dash
[i
] = req_dash
[i
] * width
;
1861 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1862 delete[] real_req_dash
;
1866 // No Memory. We use non-scaled dash pattern...
1867 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1870 #endif // GTK+ > 1.0
1872 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1873 switch (m_pen
.GetCap())
1875 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1876 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1883 capStyle
= GDK_CAP_NOT_LAST
;
1887 capStyle
= GDK_CAP_ROUND
;
1893 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1894 switch (m_pen
.GetJoin())
1896 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1897 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1899 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1902 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1904 m_pen
.GetColour().CalcPixel( m_cmap
);
1905 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1908 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1910 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1912 if (m_brush
== brush
) return;
1916 if (!m_brush
.Ok()) return;
1918 if (!m_window
) return;
1920 m_brush
.GetColour().CalcPixel( m_cmap
);
1921 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1923 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1925 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1927 if (m_brush
.GetStipple()->GetPixmap())
1929 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1930 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1934 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1935 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1939 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1941 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1942 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1945 if (IS_HATCH(m_brush
.GetStyle()))
1947 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1948 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1949 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1953 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1955 /* CMB 21/7/98: Added SetBackground. Sets background brush
1956 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1958 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1960 if (m_backgroundBrush
== brush
) return;
1962 m_backgroundBrush
= brush
;
1964 if (!m_backgroundBrush
.Ok()) return;
1966 if (!m_window
) return;
1968 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1969 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1970 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1971 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1972 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1974 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1976 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1978 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1980 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1981 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1985 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1986 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1990 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1992 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1993 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1994 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1998 void wxWindowDC::SetLogicalFunction( int function
)
2000 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2002 if (m_logicalFunction
== function
)
2005 // VZ: shouldn't this be a CHECK?
2012 case wxXOR
: mode
= GDK_XOR
; break;
2013 case wxINVERT
: mode
= GDK_INVERT
; break;
2014 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
2015 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
2016 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
2017 case wxCLEAR
: mode
= GDK_CLEAR
; break;
2018 case wxSET
: mode
= GDK_SET
; break;
2019 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
2020 case wxAND
: mode
= GDK_AND
; break;
2021 case wxOR
: mode
= GDK_OR
; break;
2022 case wxEQUIV
: mode
= GDK_EQUIV
; break;
2023 case wxNAND
: mode
= GDK_NAND
; break;
2024 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
2025 case wxCOPY
: mode
= GDK_COPY
; break;
2026 case wxNO_OP
: mode
= GDK_NOOP
; break;
2027 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
2029 // unsupported by GTK
2030 case wxNOR
: mode
= GDK_COPY
; break;
2031 #endif // GTK+ > 1.0
2033 wxFAIL_MSG( wxT("unsupported logical function") );
2037 m_logicalFunction
= function
;
2039 gdk_gc_set_function( m_penGC
, mode
);
2040 gdk_gc_set_function( m_brushGC
, mode
);
2042 // to stay compatible with wxMSW, we don't apply ROPs to the text
2043 // operations (i.e. DrawText/DrawRotatedText).
2044 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2045 gdk_gc_set_function( m_textGC
, mode
);
2048 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2050 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2052 // don't set m_textForegroundColour to an invalid colour as we'd crash
2053 // later then (we use m_textForegroundColour.GetColor() without checking
2055 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
2058 m_textForegroundColour
= col
;
2062 m_textForegroundColour
.CalcPixel( m_cmap
);
2063 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
2067 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2069 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2072 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
2075 m_textBackgroundColour
= col
;
2079 m_textBackgroundColour
.CalcPixel( m_cmap
);
2080 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
2084 void wxWindowDC::SetBackgroundMode( int mode
)
2086 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2088 m_backgroundMode
= mode
;
2090 if (!m_window
) return;
2092 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2093 // transparent/solid background mode
2095 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2097 gdk_gc_set_fill( m_brushGC
,
2098 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2102 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2104 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2107 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2109 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2111 if (!m_window
) return;
2114 rect
.x
= XLOG2DEV(x
);
2115 rect
.y
= YLOG2DEV(y
);
2116 rect
.width
= XLOG2DEVREL(width
);
2117 rect
.height
= YLOG2DEVREL(height
);
2119 if (!m_currentClippingRegion
.IsNull())
2120 m_currentClippingRegion
.Intersect( rect
);
2122 m_currentClippingRegion
.Union( rect
);
2124 #if USE_PAINT_REGION
2125 if (!m_paintClippingRegion
.IsNull())
2126 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2129 wxCoord xx
, yy
, ww
, hh
;
2130 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2131 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2133 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2134 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2135 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2136 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2139 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2141 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2145 DestroyClippingRegion();
2149 if (!m_window
) return;
2151 if (!m_currentClippingRegion
.IsNull())
2152 m_currentClippingRegion
.Intersect( region
);
2154 m_currentClippingRegion
.Union( region
);
2156 #if USE_PAINT_REGION
2157 if (!m_paintClippingRegion
.IsNull())
2158 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2161 wxCoord xx
, yy
, ww
, hh
;
2162 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2163 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2165 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2166 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2167 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2168 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2171 void wxWindowDC::DestroyClippingRegion()
2173 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2175 wxDC::DestroyClippingRegion();
2177 m_currentClippingRegion
.Clear();
2179 #if USE_PAINT_REGION
2180 if (!m_paintClippingRegion
.IsEmpty())
2181 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2184 if (!m_window
) return;
2186 if (m_currentClippingRegion
.IsEmpty())
2188 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2189 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2190 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2191 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2195 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2196 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2197 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2198 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2202 void wxWindowDC::Destroy()
2204 if (m_penGC
) wxFreePoolGC( m_penGC
);
2205 m_penGC
= (GdkGC
*) NULL
;
2206 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2207 m_brushGC
= (GdkGC
*) NULL
;
2208 if (m_textGC
) wxFreePoolGC( m_textGC
);
2209 m_textGC
= (GdkGC
*) NULL
;
2210 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2211 m_bgGC
= (GdkGC
*) NULL
;
2214 void wxWindowDC::ComputeScaleAndOrigin()
2216 /* CMB: copy scale to see if it changes */
2217 double origScaleX
= m_scaleX
;
2218 double origScaleY
= m_scaleY
;
2220 wxDC::ComputeScaleAndOrigin();
2222 /* CMB: if scale has changed call SetPen to recalulate the line width */
2223 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2226 /* this is a bit artificial, but we need to force wxDC to think
2227 the pen has changed */
2234 // Resolution in pixels per logical inch
2235 wxSize
wxWindowDC::GetPPI() const
2237 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2240 int wxWindowDC::GetDepth() const
2242 wxFAIL_MSG(wxT("not implemented"));
2248 //-----------------------------------------------------------------------------
2250 //-----------------------------------------------------------------------------
2252 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2254 wxPaintDC::wxPaintDC( wxWindow
*win
)
2257 #if USE_PAINT_REGION
2258 if (!win
->m_clipPaintRegion
)
2261 m_paintClippingRegion
= win
->GetUpdateRegion();
2262 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2265 m_paintClippingRegion
= win
->GetUpdateRegion();
2266 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2269 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2271 gdk_gc_set_clip_region( m_penGC
, region
);
2272 gdk_gc_set_clip_region( m_brushGC
, region
);
2273 gdk_gc_set_clip_region( m_textGC
, region
);
2274 gdk_gc_set_clip_region( m_bgGC
, region
);
2277 #endif // USE_PAINT_REGION
2280 //-----------------------------------------------------------------------------
2282 //-----------------------------------------------------------------------------
2284 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2286 wxClientDC::wxClientDC( wxWindow
*win
)
2289 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2291 #ifdef __WXUNIVERSAL__
2292 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2293 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2294 wxSize size
= win
->GetClientSize();
2295 SetClippingRegion(wxPoint(0, 0), size
);
2296 #endif // __WXUNIVERSAL__
2299 void wxClientDC::DoGetSize(int *width
, int *height
) const
2301 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2303 m_owner
->GetClientSize( width
, height
);
2306 // ----------------------------------------------------------------------------
2308 // ----------------------------------------------------------------------------
2310 class wxDCModule
: public wxModule
2317 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2320 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2322 bool wxDCModule::OnInit()
2328 void wxDCModule::OnExit()