]>
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, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "dcclient.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
18 #define XCopyPlane XCOPYPLANE
21 #include "wx/dcclient.h"
22 #include "wx/dcmemory.h"
24 #include "wx/module.h"
26 #include "wx/fontutil.h"
28 #include "wx/gtk/win_gtk.h"
30 #include <math.h> // for floating-point functions
34 #include <gdk/gdkprivate.h>
37 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
41 #define USE_PAINT_REGION 1
43 //-----------------------------------------------------------------------------
45 //-----------------------------------------------------------------------------
55 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
56 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
59 static GdkPixmap
*hatches
[num_hatches
];
60 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
62 extern GtkWidget
*wxGetRootWindow();
64 //-----------------------------------------------------------------------------
66 //-----------------------------------------------------------------------------
68 const double RAD2DEG
= 180.0 / M_PI
;
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
75 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
77 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
79 //-----------------------------------------------------------------------------
80 // temporary implementation of the missing GDK function
81 //-----------------------------------------------------------------------------
83 #include "gdk/gdkprivate.h"
85 void gdk_wx_draw_bitmap(GdkDrawable
*drawable
,
95 gint src_width
, src_height
;
97 GdkWindowPrivate
*drawable_private
;
98 GdkWindowPrivate
*src_private
;
99 GdkGCPrivate
*gc_private
;
102 g_return_if_fail (drawable
!= NULL
);
103 g_return_if_fail (src
!= NULL
);
104 g_return_if_fail (gc
!= NULL
);
107 if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
))
110 gdk_drawable_get_size(src
, &src_width
, &src_height
);
112 drawable_private
= (GdkWindowPrivate
*) drawable
;
113 src_private
= (GdkWindowPrivate
*) src
;
114 if (drawable_private
->destroyed
|| src_private
->destroyed
)
117 src_width
= src_private
->width
;
118 src_height
= src_private
->height
;
120 gc_private
= (GdkGCPrivate
*) gc
;
123 if (width
== -1) width
= src_width
;
124 if (height
== -1) height
= src_height
;
127 XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
),
129 GDK_WINDOW_XID(drawable
),
136 XCopyPlane( drawable_private
->xdisplay
,
137 src_private
->xwindow
,
138 drawable_private
->xwindow
,
147 //-----------------------------------------------------------------------------
148 // Implement Pool of Graphic contexts. Creating them takes too much time.
149 //-----------------------------------------------------------------------------
151 #define GC_POOL_SIZE 200
177 #define GC_POOL_ALLOC_SIZE 100
179 static int wxGCPoolSize
= 0;
181 static wxGC
*wxGCPool
= NULL
;
183 static void wxInitGCPool()
185 // This really could wait until the first call to
186 // wxGetPoolGC, but we will make the first allocation
187 // now when other initialization is being performed.
189 // Set initial pool size.
190 wxGCPoolSize
= GC_POOL_ALLOC_SIZE
;
192 // Allocate initial pool.
193 wxGCPool
= (wxGC
*)malloc(wxGCPoolSize
* sizeof(wxGC
));
194 if (wxGCPool
== NULL
)
196 // If we cannot malloc, then fail with error
197 // when debug is enabled. If debug is not enabled,
198 // the problem will eventually get caught
200 wxFAIL_MSG( wxT("Cannot allocate GC pool") );
204 // Zero initial pool.
205 memset(wxGCPool
, 0, wxGCPoolSize
* sizeof(wxGC
));
208 static void wxCleanUpGCPool()
210 for (int i
= 0; i
< wxGCPoolSize
; i
++)
212 if (wxGCPool
[i
].m_gc
)
213 gdk_gc_unref( wxGCPool
[i
].m_gc
);
221 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
225 // Look for an available GC.
226 for (int i
= 0; i
< wxGCPoolSize
; i
++)
228 if (!wxGCPool
[i
].m_gc
)
230 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
231 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
232 wxGCPool
[i
].m_type
= type
;
233 wxGCPool
[i
].m_used
= FALSE
;
235 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
237 wxGCPool
[i
].m_used
= TRUE
;
238 return wxGCPool
[i
].m_gc
;
242 // We did not find an available GC.
243 // We need to grow the GC pool.
244 pptr
= (wxGC
*)realloc(wxGCPool
,
245 (wxGCPoolSize
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
));
248 // Initialize newly allocated pool.
250 memset(&wxGCPool
[wxGCPoolSize
], 0,
251 GC_POOL_ALLOC_SIZE
*sizeof(wxGC
));
253 // Initialize entry we will return.
254 wxGCPool
[wxGCPoolSize
].m_gc
= gdk_gc_new( window
);
255 gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE
);
256 wxGCPool
[wxGCPoolSize
].m_type
= type
;
257 wxGCPool
[wxGCPoolSize
].m_used
= TRUE
;
259 // Set new value of pool size.
260 wxGCPoolSize
+= GC_POOL_ALLOC_SIZE
;
262 // Return newly allocated entry.
263 return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
;
266 // The realloc failed. Fall through to error.
267 wxFAIL_MSG( wxT("No GC available") );
269 return (GdkGC
*) NULL
;
272 static void wxFreePoolGC( GdkGC
*gc
)
274 for (int i
= 0; i
< wxGCPoolSize
; i
++)
276 if (wxGCPool
[i
].m_gc
== gc
)
278 wxGCPool
[i
].m_used
= FALSE
;
283 wxFAIL_MSG( wxT("Wrong GC") );
286 //-----------------------------------------------------------------------------
288 //-----------------------------------------------------------------------------
290 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
292 wxWindowDC::wxWindowDC()
294 m_penGC
= (GdkGC
*) NULL
;
295 m_brushGC
= (GdkGC
*) NULL
;
296 m_textGC
= (GdkGC
*) NULL
;
297 m_bgGC
= (GdkGC
*) NULL
;
298 m_cmap
= (GdkColormap
*) NULL
;
300 m_isScreenDC
= FALSE
;
301 m_owner
= (wxWindow
*)NULL
;
303 m_context
= (PangoContext
*)NULL
;
304 m_layout
= (PangoLayout
*)NULL
;
305 m_fontdesc
= (PangoFontDescription
*)NULL
;
309 wxWindowDC::wxWindowDC( wxWindow
*window
)
311 wxASSERT_MSG( window
, wxT("DC needs a window") );
313 m_penGC
= (GdkGC
*) NULL
;
314 m_brushGC
= (GdkGC
*) NULL
;
315 m_textGC
= (GdkGC
*) NULL
;
316 m_bgGC
= (GdkGC
*) NULL
;
317 m_cmap
= (GdkColormap
*) NULL
;
318 m_owner
= (wxWindow
*)NULL
;
320 m_isScreenDC
= FALSE
;
321 m_font
= window
->GetFont();
323 GtkWidget
*widget
= window
->m_wxwindow
;
325 // Some controls don't have m_wxwindow - like wxStaticBox, but the user
326 // code should still be able to create wxClientDCs for them, so we will
327 // use the parent window here then.
330 window
= window
->GetParent();
331 widget
= window
->m_wxwindow
;
334 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
337 m_context
= window
->GtkGetPangoDefaultContext();
338 m_layout
= pango_layout_new( m_context
);
339 m_fontdesc
= pango_font_description_copy( widget
->style
->font_desc
);
342 GtkPizza
*pizza
= GTK_PIZZA( widget
);
343 m_window
= pizza
->bin_window
;
345 // Window not realized ?
348 // Don't report problems as per MSW.
354 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
358 /* this must be done after SetUpDC, bacause SetUpDC calls the
359 repective SetBrush, SetPen, SetBackground etc functions
360 to set up the DC. SetBackground call m_owner->SetBackground
361 and this might not be desired as the standard dc background
362 is white whereas a window might assume gray to be the
363 standard (as e.g. wxStatusBar) */
368 wxWindowDC::~wxWindowDC()
374 g_object_unref( G_OBJECT( m_layout
) );
376 pango_font_description_free( m_fontdesc
);
380 void wxWindowDC::SetUpDC()
384 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
388 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
389 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
390 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
391 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
394 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
396 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
397 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
398 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
399 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
403 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
404 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
405 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
406 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
409 /* background colour */
410 m_backgroundBrush
= *wxWHITE_BRUSH
;
411 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
412 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
415 m_textForegroundColour
.CalcPixel( m_cmap
);
416 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
418 m_textBackgroundColour
.CalcPixel( m_cmap
);
419 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
421 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
424 m_pen
.GetColour().CalcPixel( m_cmap
);
425 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
426 gdk_gc_set_background( m_penGC
, bg_col
);
428 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
431 m_brush
.GetColour().CalcPixel( m_cmap
);
432 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
433 gdk_gc_set_background( m_brushGC
, bg_col
);
435 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
438 gdk_gc_set_background( m_bgGC
, bg_col
);
439 gdk_gc_set_foreground( m_bgGC
, bg_col
);
441 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
444 gdk_gc_set_function( m_textGC
, GDK_COPY
);
445 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
446 gdk_gc_set_function( m_penGC
, GDK_COPY
);
449 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
450 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
451 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
452 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
456 hatch_bitmap
= hatches
;
457 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
458 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
459 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
460 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
461 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
462 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
466 void wxWindowDC::DoGetSize( int* width
, int* height
) const
468 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
470 m_owner
->GetSize(width
, height
);
473 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
474 const wxColour
& col
, int style
);
476 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
477 const wxColour
& col
, int style
)
479 return wxDoFloodFill(this, x
, y
, col
, style
);
482 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
484 // Generic (and therefore rather inefficient) method.
485 // Could be improved.
487 wxBitmap
bitmap(1, 1);
488 memdc
.SelectObject(bitmap
);
489 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
490 memdc
.SelectObject(wxNullBitmap
);
492 wxImage image
= bitmap
.ConvertToImage();
493 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
497 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
499 wxCHECK_RET( Ok(), wxT("invalid window dc") );
501 if (m_pen
.GetStyle() != wxTRANSPARENT
)
504 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
506 CalcBoundingBox(x1
, y1
);
507 CalcBoundingBox(x2
, y2
);
511 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
513 wxCHECK_RET( Ok(), wxT("invalid window dc") );
515 if (m_pen
.GetStyle() != wxTRANSPARENT
)
520 wxCoord xx
= XLOG2DEV(x
);
521 wxCoord yy
= YLOG2DEV(y
);
524 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
525 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
530 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
531 wxCoord xc
, wxCoord yc
)
533 wxCHECK_RET( Ok(), wxT("invalid window dc") );
535 wxCoord xx1
= XLOG2DEV(x1
);
536 wxCoord yy1
= YLOG2DEV(y1
);
537 wxCoord xx2
= XLOG2DEV(x2
);
538 wxCoord yy2
= YLOG2DEV(y2
);
539 wxCoord xxc
= XLOG2DEV(xc
);
540 wxCoord yyc
= YLOG2DEV(yc
);
541 double dx
= xx1
- xxc
;
542 double dy
= yy1
- yyc
;
543 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
544 wxCoord r
= (wxCoord
)radius
;
545 double radius1
, radius2
;
547 if (xx1
== xx2
&& yy1
== yy2
)
555 radius1
= radius2
= 0.0;
559 radius1
= (xx1
- xxc
== 0) ?
560 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
561 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
562 radius2
= (xx2
- xxc
== 0) ?
563 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
564 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
566 wxCoord alpha1
= wxCoord(radius1
* 64.0);
567 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
568 while (alpha2
<= 0) alpha2
+= 360*64;
569 while (alpha1
> 360*64) alpha1
-= 360*64;
573 if (m_brush
.GetStyle() != wxTRANSPARENT
)
575 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
577 gdk_gc_set_ts_origin( m_textGC
,
578 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
579 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
580 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
581 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
583 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
585 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
586 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
587 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
589 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
591 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
592 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
593 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
595 if (m_brush
.GetStyle() == wxSTIPPLE
)
597 gdk_gc_set_ts_origin( m_brushGC
,
598 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
599 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
600 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
601 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
605 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
609 if (m_pen
.GetStyle() != wxTRANSPARENT
)
611 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
613 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
614 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
618 CalcBoundingBox (x1
, y1
);
619 CalcBoundingBox (x2
, y2
);
622 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
624 wxCHECK_RET( Ok(), wxT("invalid window dc") );
626 wxCoord xx
= XLOG2DEV(x
);
627 wxCoord yy
= YLOG2DEV(y
);
628 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
629 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
631 // CMB: handle -ve width and/or height
632 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
633 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
637 wxCoord start
= wxCoord(sa
* 64.0);
638 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
640 if (m_brush
.GetStyle() != wxTRANSPARENT
)
642 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
644 gdk_gc_set_ts_origin( m_textGC
,
645 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
646 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
647 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
648 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
650 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
652 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
653 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
654 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
656 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
658 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
659 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
660 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
662 if (m_brush
.GetStyle() == wxSTIPPLE
)
664 gdk_gc_set_ts_origin( m_brushGC
,
665 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
666 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
667 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
668 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
672 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
676 if (m_pen
.GetStyle() != wxTRANSPARENT
)
677 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
680 CalcBoundingBox (x
, y
);
681 CalcBoundingBox (x
+ width
, y
+ height
);
684 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
686 wxCHECK_RET( Ok(), wxT("invalid window dc") );
688 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
689 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
691 CalcBoundingBox (x
, y
);
694 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
696 wxCHECK_RET( Ok(), wxT("invalid window dc") );
698 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
701 GdkPoint
*gpts
= new GdkPoint
[n
];
704 wxFAIL_MSG( wxT("Cannot allocate PolyLine") );
708 for (int i
= 0; i
< n
; i
++)
710 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
711 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
);
713 CalcBoundingBox( x1
+ xoffset
, y1
+ yoffset
);
720 gdk_draw_lines( m_window
, m_penGC
, gpts
, n
);
725 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
727 wxCHECK_RET( Ok(), wxT("invalid window dc") );
731 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
733 for (i
= 0 ; i
< n
; i
++)
735 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
736 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
738 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
743 if (m_brush
.GetStyle() != wxTRANSPARENT
)
745 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
747 gdk_gc_set_ts_origin( m_textGC
,
748 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
749 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
750 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
751 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
753 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
755 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
756 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
757 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
759 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
761 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
762 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
763 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
765 if (m_brush
.GetStyle() == wxSTIPPLE
)
767 gdk_gc_set_ts_origin( m_brushGC
,
768 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
769 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
770 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
771 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
775 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
779 if (m_pen
.GetStyle() != wxTRANSPARENT
)
781 for (i
= 0 ; i
< n
; i
++)
783 gdk_draw_line( m_window
, m_penGC
,
786 gdkpoints
[(i
+1)%n
].x
,
787 gdkpoints
[(i
+1)%n
].y
);
795 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
797 wxCHECK_RET( Ok(), wxT("invalid window dc") );
799 wxCoord xx
= XLOG2DEV(x
);
800 wxCoord yy
= YLOG2DEV(y
);
801 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
802 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
804 // CMB: draw nothing if transformed w or h is 0
805 if (ww
== 0 || hh
== 0) return;
807 // CMB: handle -ve width and/or height
808 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
809 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
813 if (m_brush
.GetStyle() != wxTRANSPARENT
)
815 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
817 gdk_gc_set_ts_origin( m_textGC
,
818 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
819 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
820 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
821 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
823 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
825 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
826 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
827 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
829 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
831 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
832 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
833 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
835 if (m_brush
.GetStyle() == wxSTIPPLE
)
837 gdk_gc_set_ts_origin( m_brushGC
,
838 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
839 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
840 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
841 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
845 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
849 if (m_pen
.GetStyle() != wxTRANSPARENT
)
850 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
853 CalcBoundingBox( x
, y
);
854 CalcBoundingBox( x
+ width
, y
+ height
);
857 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
859 wxCHECK_RET( Ok(), wxT("invalid window dc") );
861 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
863 wxCoord xx
= XLOG2DEV(x
);
864 wxCoord yy
= YLOG2DEV(y
);
865 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
866 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
867 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
869 // CMB: handle -ve width and/or height
870 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
871 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
873 // CMB: if radius is zero use DrawRectangle() instead to avoid
874 // X drawing errors with small radii
877 DrawRectangle( x
, y
, width
, height
);
881 // CMB: draw nothing if transformed w or h is 0
882 if (ww
== 0 || hh
== 0) return;
884 // CMB: adjust size if outline is drawn otherwise the result is
885 // 1 pixel too wide and high
886 if (m_pen
.GetStyle() != wxTRANSPARENT
)
894 // CMB: ensure dd is not larger than rectangle otherwise we
895 // get an hour glass shape
897 if (dd
> ww
) dd
= ww
;
898 if (dd
> hh
) dd
= hh
;
901 if (m_brush
.GetStyle() != wxTRANSPARENT
)
903 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
905 gdk_gc_set_ts_origin( m_textGC
,
906 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
907 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
908 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
909 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
910 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
911 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
912 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
913 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
914 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
916 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
918 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
919 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
920 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
921 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
922 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
923 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
924 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
925 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
927 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
929 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
930 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
931 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
932 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
933 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
934 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
935 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
936 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
938 if (m_brush
.GetStyle() == wxSTIPPLE
)
940 gdk_gc_set_ts_origin( m_brushGC
,
941 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
942 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
943 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
944 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
945 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
946 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
947 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
948 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
949 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
953 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
954 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
955 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
956 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
957 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
958 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
962 if (m_pen
.GetStyle() != wxTRANSPARENT
)
964 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
965 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
966 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
967 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
968 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
969 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
970 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
971 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
975 // this ignores the radius
976 CalcBoundingBox( x
, y
);
977 CalcBoundingBox( x
+ width
, y
+ height
);
980 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
982 wxCHECK_RET( Ok(), wxT("invalid window dc") );
984 wxCoord xx
= XLOG2DEV(x
);
985 wxCoord yy
= YLOG2DEV(y
);
986 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
987 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
989 // CMB: handle -ve width and/or height
990 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
991 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
995 if (m_brush
.GetStyle() != wxTRANSPARENT
)
997 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
999 gdk_gc_set_ts_origin( m_textGC
,
1000 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1001 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1002 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1003 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
1005 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
1007 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
1008 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1009 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1011 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
1013 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
1014 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1015 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1017 if (m_brush
.GetStyle() == wxSTIPPLE
)
1019 gdk_gc_set_ts_origin( m_brushGC
,
1020 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1021 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1022 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1023 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1027 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1031 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1032 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1035 CalcBoundingBox( x
, y
);
1036 CalcBoundingBox( x
+ width
, y
+ height
);
1039 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1041 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1042 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1045 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1046 wxCoord x
, wxCoord y
,
1049 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1051 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1053 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1055 /* scale/translate size and position */
1056 int xx
= XLOG2DEV(x
);
1057 int yy
= YLOG2DEV(y
);
1059 int w
= bitmap
.GetWidth();
1060 int h
= bitmap
.GetHeight();
1062 CalcBoundingBox( x
, y
);
1063 CalcBoundingBox( x
+ w
, y
+ h
);
1065 if (!m_window
) return;
1067 int ww
= XLOG2DEVREL(w
);
1068 int hh
= YLOG2DEVREL(h
);
1070 /* compare to current clipping region */
1071 if (!m_currentClippingRegion
.IsNull())
1073 wxRegion
tmp( xx
,yy
,ww
,hh
);
1074 tmp
.Intersect( m_currentClippingRegion
);
1079 /* scale bitmap if required */
1080 wxBitmap use_bitmap
;
1081 if ((w
!= ww
) || (h
!= hh
))
1083 wxImage image
= bitmap
.ConvertToImage();
1084 image
.Rescale( ww
, hh
);
1086 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1088 use_bitmap
= wxBitmap(image
);
1092 use_bitmap
= bitmap
;
1095 /* apply mask if any */
1096 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1097 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1099 if (useMask
&& mask
)
1101 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1102 #ifndef __WXGTK20__ // TODO fix crash
1103 if (!m_currentClippingRegion
.IsNull())
1106 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1107 GdkGC
*gc
= gdk_gc_new( new_mask
);
1109 gdk_gc_set_foreground( gc
, &col
);
1110 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1112 gdk_gc_set_background( gc
, &col
);
1114 gdk_gc_set_foreground( gc
, &col
);
1115 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1116 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1117 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1118 gdk_gc_set_stipple( gc
, mask
);
1119 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1126 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1128 gdk_gc_set_clip_mask( m_textGC
, mask
);
1129 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1134 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1136 gdk_gc_set_clip_mask( m_penGC
, mask
);
1137 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1141 gdk_bitmap_unref( new_mask
);
1144 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1145 drawing a mono-bitmap (XBitmap) we use the current text GC */
1147 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1149 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1151 /* remove mask again if any */
1152 if (useMask
&& mask
)
1156 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1157 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1158 if (!m_currentClippingRegion
.IsNull())
1159 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1163 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1164 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1165 if (!m_currentClippingRegion
.IsNull())
1166 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1171 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1172 wxCoord width
, wxCoord height
,
1174 wxCoord xsrc
, wxCoord ysrc
,
1177 wxCoord xsrcMask
, wxCoord ysrcMask
)
1179 /* this is the nth try to get this utterly useless function to
1180 work. it now completely ignores the scaling or translation
1181 of the source dc, but scales correctly on the target dc and
1182 knows about possible mask information in a memory dc. */
1184 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1186 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1188 if (!m_window
) return FALSE
;
1191 // transform the source DC coords to the device ones
1192 xsrc
= source
->XLOG2DEV(xsrc
);
1193 ysrc
= source
->YLOG2DEV(ysrc
);
1196 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1197 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1199 bool use_bitmap_method
= FALSE
;
1200 bool is_mono
= FALSE
;
1202 /* TODO: use the mask origin when drawing transparently */
1203 if (xsrcMask
== -1 && ysrcMask
== -1)
1205 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1208 if (srcDC
->m_isMemDC
)
1210 if (!memDC
->m_selected
.Ok()) return FALSE
;
1212 /* we use the "XCopyArea" way to copy a memory dc into
1213 y different window if the memory dc BOTH
1214 a) doesn't have any mask or its mask isn't used
1218 if (useMask
&& (memDC
->m_selected
.GetMask()))
1220 /* we HAVE TO use the direct way for memory dcs
1221 that have mask since the XCopyArea doesn't know
1223 use_bitmap_method
= TRUE
;
1225 else if (memDC
->m_selected
.GetDepth() == 1)
1227 /* we HAVE TO use the direct way for memory dcs
1228 that are bitmaps because XCopyArea doesn't cope
1229 with different bit depths */
1231 use_bitmap_method
= TRUE
;
1233 else if ((xsrc
== 0) && (ysrc
== 0) &&
1234 (width
== memDC
->m_selected
.GetWidth()) &&
1235 (height
== memDC
->m_selected
.GetHeight()))
1237 /* we SHOULD use the direct way if all of the bitmap
1238 in the memory dc is copied in which case XCopyArea
1239 wouldn't be able able to boost performace by reducing
1240 the area to be scaled */
1241 use_bitmap_method
= TRUE
;
1245 use_bitmap_method
= FALSE
;
1249 CalcBoundingBox( xdest
, ydest
);
1250 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1252 /* scale/translate size and position */
1253 wxCoord xx
= XLOG2DEV(xdest
);
1254 wxCoord yy
= YLOG2DEV(ydest
);
1256 wxCoord ww
= XLOG2DEVREL(width
);
1257 wxCoord hh
= YLOG2DEVREL(height
);
1259 /* compare to current clipping region */
1260 if (!m_currentClippingRegion
.IsNull())
1262 wxRegion
tmp( xx
,yy
,ww
,hh
);
1263 tmp
.Intersect( m_currentClippingRegion
);
1268 int old_logical_func
= m_logicalFunction
;
1269 SetLogicalFunction( logical_func
);
1271 if (use_bitmap_method
)
1273 /* scale/translate bitmap size */
1274 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1275 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1277 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1278 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1280 /* scale bitmap if required */
1281 wxBitmap use_bitmap
;
1283 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1285 wxImage image
= memDC
->m_selected
.ConvertToImage();
1286 image
= image
.Scale( bm_ww
, bm_hh
);
1289 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1291 use_bitmap
= wxBitmap(image
);
1295 use_bitmap
= memDC
->m_selected
;
1298 /* apply mask if any */
1299 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1300 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1302 if (useMask
&& mask
)
1304 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1305 #ifndef __WXGTK20__ // TODO fix crash
1306 if (!m_currentClippingRegion
.IsNull())
1309 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1310 GdkGC
*gc
= gdk_gc_new( new_mask
);
1312 gdk_gc_set_foreground( gc
, &col
);
1313 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1315 gdk_gc_set_background( gc
, &col
);
1317 gdk_gc_set_foreground( gc
, &col
);
1318 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1319 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1320 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1321 gdk_gc_set_stipple( gc
, mask
);
1322 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1329 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1331 gdk_gc_set_clip_mask( m_textGC
, mask
);
1332 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1337 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1339 gdk_gc_set_clip_mask( m_penGC
, mask
);
1340 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1343 gdk_bitmap_unref( new_mask
);
1346 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1347 drawing a mono-bitmap (XBitmap) we use the current text GC */
1350 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1352 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1354 /* remove mask again if any */
1355 if (useMask
&& mask
)
1359 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1360 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1361 if (!m_currentClippingRegion
.IsNull())
1362 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1366 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1367 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1368 if (!m_currentClippingRegion
.IsNull())
1369 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1373 else /* use_bitmap_method */
1375 if ((width
!= ww
) || (height
!= hh
))
1377 /* draw source window into a bitmap as we cannot scale
1378 a window in contrast to a bitmap. this would actually
1379 work with memory dcs as well, but we'd lose the mask
1380 information and waste one step in this process since
1381 a memory already has a bitmap. all this is slightly
1382 inefficient as we could take an XImage directly from
1383 an X window, but we'd then also have to care that
1384 the window is not outside the screen (in which case
1385 we'd get a BadMatch or what not).
1386 Is a double XGetImage and combined XGetPixel and
1387 XPutPixel really faster? I'm not sure. look at wxXt
1388 for a different implementation of the same problem. */
1390 wxBitmap
bitmap( width
, height
);
1392 /* copy including child window contents */
1393 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1394 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1396 xsrc
, ysrc
, width
, height
);
1397 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1400 wxImage image
= bitmap
.ConvertToImage();
1401 image
= image
.Scale( ww
, hh
);
1403 /* convert to bitmap */
1404 bitmap
= wxBitmap(image
);
1406 /* draw scaled bitmap */
1407 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1412 /* No scaling and not a memory dc with a mask either */
1414 /* copy including child window contents */
1415 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1416 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1418 xsrc
, ysrc
, width
, height
);
1419 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1423 SetLogicalFunction( old_logical_func
);
1427 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1429 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1431 if (!m_window
) return;
1433 if (text
.empty()) return;
1436 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1438 wxCHECK_RET( font
, wxT("invalid font") );
1445 wxCHECK_RET( m_context
, wxT("no Pango context") );
1446 wxCHECK_RET( m_layout
, wxT("no Pango layout") );
1447 wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") );
1450 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
1452 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( text
);
1453 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1455 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1459 if (m_scaleY
!= 1.0)
1461 // If there is a user or actually any scale applied to
1462 // the device context, scale the font.
1464 // scale font description
1465 gint oldSize
= pango_font_description_get_size( m_fontdesc
);
1466 double size
= oldSize
;
1467 size
= size
* m_scaleY
;
1468 pango_font_description_set_size( m_fontdesc
, (gint
)size
);
1470 // actually apply scaled font
1471 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1473 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1474 if ( m_backgroundMode
== wxSOLID
)
1476 gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor());
1477 gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
);
1478 gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor());
1482 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1484 // reset unscaled size
1485 pango_font_description_set_size( m_fontdesc
, oldSize
);
1487 // actually apply unscaled font
1488 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1492 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1493 if ( m_backgroundMode
== wxSOLID
)
1495 gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor());
1496 gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
);
1497 gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor());
1500 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1507 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1508 wxCoord height
= font
->ascent
+ font
->descent
;
1510 if ( m_backgroundMode
== wxSOLID
)
1512 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1513 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1514 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1516 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1518 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1519 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1520 properties (see wxXt implementation) */
1521 if (m_font
.GetUnderlined())
1523 wxCoord ul_y
= y
+ font
->ascent
;
1524 if (font
->descent
> 0) ul_y
++;
1525 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1527 #endif // GTK+ 2.0/1.x
1529 width
= wxCoord(width
/ m_scaleX
);
1530 height
= wxCoord(height
/ m_scaleY
);
1531 CalcBoundingBox (x
+ width
, y
+ height
);
1532 CalcBoundingBox (x
, y
);
1535 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1539 DrawText(text
, x
, y
);
1543 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1545 if (!m_window
) return;
1548 // implement later without GdkFont for GTK 2.0
1551 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1553 wxCHECK_RET( font
, wxT("invalid font") );
1555 // the size of the text
1556 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1557 wxCoord h
= font
->ascent
+ font
->descent
;
1559 // draw the string normally
1562 dc
.SelectObject(src
);
1563 dc
.SetFont(GetFont());
1564 dc
.SetBackground(*wxWHITE_BRUSH
);
1565 dc
.SetBrush(*wxBLACK_BRUSH
);
1567 dc
.DrawText(text
, 0, 0);
1568 dc
.SelectObject(wxNullBitmap
);
1570 // Calculate the size of the rotated bounding box.
1571 double rad
= DegToRad(angle
);
1572 double dx
= cos(rad
),
1575 // the rectngle vertices are counted clockwise with the first one being at
1576 // (0, 0) (or, rather, at (x, y))
1578 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1581 double x3
= x4
+ x2
,
1585 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1586 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1587 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1588 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1590 // prepare to blit-with-rotate the bitmap to the DC
1591 wxImage image
= src
.ConvertToImage();
1593 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1594 *colBack
= m_textBackgroundColour
.GetColor();
1596 bool textColSet
= TRUE
;
1598 unsigned char *data
= image
.GetData();
1600 // paint pixel by pixel
1601 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1603 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1605 // transform source coords to dest coords
1606 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1607 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1608 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1609 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1612 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1613 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1615 // change colour if needed
1616 if ( textPixel
!= textColSet
)
1618 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1621 textColSet
= textPixel
;
1624 // don't use DrawPoint() because it uses the current pen
1625 // colour, and we don't need it here
1626 gdk_draw_point( m_window
, m_textGC
,
1627 XLOG2DEV(x
) + dstX
, YLOG2DEV(y
) + dstY
);
1632 // it would be better to draw with non underlined font and draw the line
1633 // manually here (it would be more straight...)
1635 if ( m_font
.GetUnderlined() )
1637 gdk_draw_line( m_window
, m_textGC
,
1638 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1639 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1643 // restore the font colour
1644 gdk_gc_set_foreground( m_textGC
, colText
);
1646 // update the bounding box
1647 CalcBoundingBox(x
+ minX
, y
+ minY
);
1648 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1652 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1653 wxCoord
*width
, wxCoord
*height
,
1654 wxCoord
*descent
, wxCoord
*externalLeading
,
1655 wxFont
*theFont
) const
1657 if (string
.IsEmpty())
1659 if (width
) (*width
) = 0;
1660 if (height
) (*height
) = 0;
1665 // Set new font description
1667 pango_layout_set_font_description( m_layout
, theFont
->GetNativeFontInfo()->description
);
1669 // Set layout's text
1671 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
1672 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1674 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( string
);
1675 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1676 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1680 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1682 if (width
) (*width
) = (wxCoord
) w
;
1683 if (height
) (*height
) = (wxCoord
) h
;
1686 // Do something about metrics here. TODO.
1689 if (externalLeading
) (*externalLeading
) = 0; // ??
1691 // Reset old font description
1693 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1695 wxFont fontToUse
= m_font
;
1696 if (theFont
) fontToUse
= *theFont
;
1698 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1699 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1700 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1701 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1702 if (externalLeading
) (*externalLeading
) = 0; // ??
1706 wxCoord
wxWindowDC::GetCharWidth() const
1709 pango_layout_set_text( m_layout
, "H", 1 );
1711 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1714 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1715 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1717 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1721 wxCoord
wxWindowDC::GetCharHeight() const
1724 pango_layout_set_text( m_layout
, "H", 1 );
1726 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1729 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1730 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1732 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1736 void wxWindowDC::Clear()
1738 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1740 if (!m_window
) return;
1742 // VZ: the code below results in infinite recursion and crashes when
1743 // dc.Clear() is done from OnPaint() so I disable it for now.
1744 // I don't know what the correct fix is but Clear() surely should not
1745 // reenter OnPaint()!
1747 /* - we either are a memory dc or have a window as the
1748 owner. anything else shouldn't happen.
1749 - we don't use gdk_window_clear() as we don't set
1750 the window's background colour anymore. it is too
1751 much pain to keep the DC's and the window's back-
1752 ground colour in synch. */
1763 GetSize( &width
, &height
);
1764 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1769 GetSize( &width
, &height
);
1770 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1774 void wxWindowDC::SetFont( const wxFont
&font
)
1782 pango_font_description_free( m_fontdesc
);
1784 m_fontdesc
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description
);
1789 PangoContext
*oldContext
= m_context
;
1791 // We might want to use the X11 context for faster
1792 // rendering on screen
1793 if (m_font
.GetNoAntiAliasing())
1794 m_context
= m_owner
->GtkGetPangoX11Context();
1796 m_context
= m_owner
->GtkGetPangoDefaultContext();
1798 // If we switch back/forth between different contexts
1799 // we also have to create a new layout. I think so,
1800 // at least, and it doesn't hurt to do it.
1801 if (oldContext
!= m_context
)
1804 g_object_unref( G_OBJECT( m_layout
) );
1806 m_layout
= pango_layout_new( m_context
);
1810 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1815 void wxWindowDC::SetPen( const wxPen
&pen
)
1817 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1819 if (m_pen
== pen
) return;
1823 if (!m_pen
.Ok()) return;
1825 if (!m_window
) return;
1827 gint width
= m_pen
.GetWidth();
1830 // CMB: if width is non-zero scale it with the dc
1835 // X doesn't allow different width in x and y and so we take
1838 ( fabs((double) XLOG2DEVREL(width
)) +
1839 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1843 static const wxGTKDash dotted
[] = {1, 1};
1844 static const wxGTKDash short_dashed
[] = {2, 2};
1845 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1846 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1848 // We express dash pattern in pen width unit, so we are
1849 // independent of zoom factor and so on...
1851 const wxGTKDash
*req_dash
;
1853 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1854 switch (m_pen
.GetStyle())
1858 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1859 req_nb_dash
= m_pen
.GetDashCount();
1860 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1865 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1872 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1874 req_dash
= wxCoord_dashed
;
1879 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1881 req_dash
= short_dashed
;
1886 // lineStyle = GDK_LINE_DOUBLE_DASH;
1887 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1889 req_dash
= dotted_dashed
;
1894 case wxSTIPPLE_MASK_OPAQUE
:
1899 lineStyle
= GDK_LINE_SOLID
;
1900 req_dash
= (wxGTKDash
*)NULL
;
1906 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1907 if (req_dash
&& req_nb_dash
)
1909 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1912 for (int i
= 0; i
< req_nb_dash
; i
++)
1913 real_req_dash
[i
] = req_dash
[i
] * width
;
1914 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1915 delete[] real_req_dash
;
1919 // No Memory. We use non-scaled dash pattern...
1920 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1923 #endif // GTK+ > 1.0
1925 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1926 switch (m_pen
.GetCap())
1928 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1929 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1936 capStyle
= GDK_CAP_NOT_LAST
;
1940 capStyle
= GDK_CAP_ROUND
;
1946 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1947 switch (m_pen
.GetJoin())
1949 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1950 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1952 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1955 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1957 m_pen
.GetColour().CalcPixel( m_cmap
);
1958 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1961 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1963 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1965 if (m_brush
== brush
) return;
1969 if (!m_brush
.Ok()) return;
1971 if (!m_window
) return;
1973 m_brush
.GetColour().CalcPixel( m_cmap
);
1974 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1976 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1978 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1980 if (m_brush
.GetStipple()->GetPixmap())
1982 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1983 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1987 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1988 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1992 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1994 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1995 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1998 if (IS_HATCH(m_brush
.GetStyle()))
2000 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
2001 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
2002 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
2006 void wxWindowDC::SetBackground( const wxBrush
&brush
)
2008 /* CMB 21/7/98: Added SetBackground. Sets background brush
2009 * for Clear() and bg colour for shapes filled with cross-hatch brush */
2011 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2013 if (m_backgroundBrush
== brush
) return;
2015 m_backgroundBrush
= brush
;
2017 if (!m_backgroundBrush
.Ok()) return;
2019 if (!m_window
) return;
2021 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
2022 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
2023 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
2024 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2025 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2027 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
2029 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
2031 if (m_backgroundBrush
.GetStipple()->GetPixmap())
2033 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
2034 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
2038 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2039 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
2043 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
2045 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2046 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
2047 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
2051 void wxWindowDC::SetLogicalFunction( int function
)
2053 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2055 if (m_logicalFunction
== function
)
2058 // VZ: shouldn't this be a CHECK?
2065 case wxXOR
: mode
= GDK_XOR
; break;
2066 case wxINVERT
: mode
= GDK_INVERT
; break;
2067 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
2068 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
2069 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
2070 case wxCLEAR
: mode
= GDK_CLEAR
; break;
2071 case wxSET
: mode
= GDK_SET
; break;
2072 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
2073 case wxAND
: mode
= GDK_AND
; break;
2074 case wxOR
: mode
= GDK_OR
; break;
2075 case wxEQUIV
: mode
= GDK_EQUIV
; break;
2076 case wxNAND
: mode
= GDK_NAND
; break;
2077 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
2078 case wxCOPY
: mode
= GDK_COPY
; break;
2079 case wxNO_OP
: mode
= GDK_NOOP
; break;
2080 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
2082 // unsupported by GTK
2083 case wxNOR
: mode
= GDK_COPY
; break;
2084 #endif // GTK+ > 1.0
2086 wxFAIL_MSG( wxT("unsupported logical function") );
2090 m_logicalFunction
= function
;
2092 gdk_gc_set_function( m_penGC
, mode
);
2093 gdk_gc_set_function( m_brushGC
, mode
);
2095 // to stay compatible with wxMSW, we don't apply ROPs to the text
2096 // operations (i.e. DrawText/DrawRotatedText).
2097 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2098 gdk_gc_set_function( m_textGC
, mode
);
2101 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2103 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2105 // don't set m_textForegroundColour to an invalid colour as we'd crash
2106 // later then (we use m_textForegroundColour.GetColor() without checking
2108 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
2111 m_textForegroundColour
= col
;
2115 m_textForegroundColour
.CalcPixel( m_cmap
);
2116 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
2120 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2122 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2125 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
2128 m_textBackgroundColour
= col
;
2132 m_textBackgroundColour
.CalcPixel( m_cmap
);
2133 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
2137 void wxWindowDC::SetBackgroundMode( int mode
)
2139 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2141 m_backgroundMode
= mode
;
2143 if (!m_window
) return;
2145 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2146 // transparent/solid background mode
2148 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2150 gdk_gc_set_fill( m_brushGC
,
2151 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2155 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2157 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2160 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2162 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2164 if (!m_window
) return;
2167 rect
.x
= XLOG2DEV(x
);
2168 rect
.y
= YLOG2DEV(y
);
2169 rect
.width
= XLOG2DEVREL(width
);
2170 rect
.height
= YLOG2DEVREL(height
);
2172 if (!m_currentClippingRegion
.IsNull())
2173 m_currentClippingRegion
.Intersect( rect
);
2175 m_currentClippingRegion
.Union( rect
);
2177 #if USE_PAINT_REGION
2178 if (!m_paintClippingRegion
.IsNull())
2179 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2182 wxCoord xx
, yy
, ww
, hh
;
2183 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2184 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2186 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2187 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2188 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2189 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2192 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2194 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2198 DestroyClippingRegion();
2202 if (!m_window
) return;
2204 if (!m_currentClippingRegion
.IsNull())
2205 m_currentClippingRegion
.Intersect( region
);
2207 m_currentClippingRegion
.Union( region
);
2209 #if USE_PAINT_REGION
2210 if (!m_paintClippingRegion
.IsNull())
2211 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2214 wxCoord xx
, yy
, ww
, hh
;
2215 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2216 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2218 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2219 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2220 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2221 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2224 void wxWindowDC::DestroyClippingRegion()
2226 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2228 wxDC::DestroyClippingRegion();
2230 m_currentClippingRegion
.Clear();
2232 #if USE_PAINT_REGION
2233 if (!m_paintClippingRegion
.IsEmpty())
2234 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2237 if (!m_window
) return;
2239 if (m_currentClippingRegion
.IsEmpty())
2241 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2242 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2243 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2244 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2248 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2249 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2250 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2251 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2255 void wxWindowDC::Destroy()
2257 if (m_penGC
) wxFreePoolGC( m_penGC
);
2258 m_penGC
= (GdkGC
*) NULL
;
2259 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2260 m_brushGC
= (GdkGC
*) NULL
;
2261 if (m_textGC
) wxFreePoolGC( m_textGC
);
2262 m_textGC
= (GdkGC
*) NULL
;
2263 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2264 m_bgGC
= (GdkGC
*) NULL
;
2267 void wxWindowDC::ComputeScaleAndOrigin()
2269 /* CMB: copy scale to see if it changes */
2270 double origScaleX
= m_scaleX
;
2271 double origScaleY
= m_scaleY
;
2273 wxDC::ComputeScaleAndOrigin();
2275 /* CMB: if scale has changed call SetPen to recalulate the line width */
2276 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2279 /* this is a bit artificial, but we need to force wxDC to think
2280 the pen has changed */
2287 // Resolution in pixels per logical inch
2288 wxSize
wxWindowDC::GetPPI() const
2290 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2293 int wxWindowDC::GetDepth() const
2295 wxFAIL_MSG(wxT("not implemented"));
2301 //-----------------------------------------------------------------------------
2303 //-----------------------------------------------------------------------------
2305 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2307 wxPaintDC::wxPaintDC( wxWindow
*win
)
2310 #if USE_PAINT_REGION
2311 if (!win
->m_clipPaintRegion
)
2314 m_paintClippingRegion
= win
->GetUpdateRegion();
2315 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2318 m_paintClippingRegion
= win
->GetUpdateRegion();
2319 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2322 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2324 gdk_gc_set_clip_region( m_penGC
, region
);
2325 gdk_gc_set_clip_region( m_brushGC
, region
);
2326 gdk_gc_set_clip_region( m_textGC
, region
);
2327 gdk_gc_set_clip_region( m_bgGC
, region
);
2330 #endif // USE_PAINT_REGION
2333 //-----------------------------------------------------------------------------
2335 //-----------------------------------------------------------------------------
2337 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2339 wxClientDC::wxClientDC( wxWindow
*win
)
2342 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2344 #ifdef __WXUNIVERSAL__
2345 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2346 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2347 wxSize size
= win
->GetClientSize();
2348 SetClippingRegion(wxPoint(0, 0), size
);
2349 #endif // __WXUNIVERSAL__
2352 void wxClientDC::DoGetSize(int *width
, int *height
) const
2354 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2356 m_owner
->GetClientSize( width
, height
);
2359 // ----------------------------------------------------------------------------
2361 // ----------------------------------------------------------------------------
2363 class wxDCModule
: public wxModule
2370 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2373 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2375 bool wxDCModule::OnInit()
2381 void wxDCModule::OnExit()