]>
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 /////////////////////////////////////////////////////////////////////////////
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_layout
= (PangoLayout
*)NULL
;
302 m_fontdesc
= (PangoFontDescription
*)NULL
;
306 wxWindowDC::wxWindowDC( wxWindow
*window
)
308 wxASSERT_MSG( window
, wxT("DC needs a window") );
310 m_penGC
= (GdkGC
*) NULL
;
311 m_brushGC
= (GdkGC
*) NULL
;
312 m_textGC
= (GdkGC
*) NULL
;
313 m_bgGC
= (GdkGC
*) NULL
;
314 m_cmap
= (GdkColormap
*) NULL
;
315 m_owner
= (wxWindow
*)NULL
;
317 m_isScreenDC
= FALSE
;
318 m_font
= window
->GetFont();
320 GtkWidget
*widget
= window
->m_wxwindow
;
322 // Some controls don't have m_wxwindow - like wxStaticBox, but the user
323 // code should still be able to create wxClientDCs for them, so we will
324 // use the parent window here then.
327 window
= window
->GetParent();
328 widget
= window
->m_wxwindow
;
331 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
334 m_context
= window
->GtkGetPangoDefaultContext();
335 m_layout
= pango_layout_new( m_context
);
336 m_fontdesc
= pango_font_description_copy( widget
->style
->font_desc
);
339 GtkPizza
*pizza
= GTK_PIZZA( widget
);
340 m_window
= pizza
->bin_window
;
342 // Window not realized ?
345 // Don't report problems as per MSW.
351 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
355 /* this must be done after SetUpDC, bacause SetUpDC calls the
356 repective SetBrush, SetPen, SetBackground etc functions
357 to set up the DC. SetBackground call m_owner->SetBackground
358 and this might not be desired as the standard dc background
359 is white whereas a window might assume gray to be the
360 standard (as e.g. wxStatusBar) */
365 wxWindowDC::~wxWindowDC()
371 g_object_unref( G_OBJECT( m_layout
) );
373 pango_font_description_free( m_fontdesc
);
377 void wxWindowDC::SetUpDC()
381 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
385 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
386 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
387 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
388 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
391 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
393 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
394 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
395 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
396 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
400 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
401 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
402 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
403 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
406 /* background colour */
407 m_backgroundBrush
= *wxWHITE_BRUSH
;
408 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
409 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
412 m_textForegroundColour
.CalcPixel( m_cmap
);
413 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
415 m_textBackgroundColour
.CalcPixel( m_cmap
);
416 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
418 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
421 m_pen
.GetColour().CalcPixel( m_cmap
);
422 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
423 gdk_gc_set_background( m_penGC
, bg_col
);
425 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
428 m_brush
.GetColour().CalcPixel( m_cmap
);
429 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
430 gdk_gc_set_background( m_brushGC
, bg_col
);
432 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
435 gdk_gc_set_background( m_bgGC
, bg_col
);
436 gdk_gc_set_foreground( m_bgGC
, bg_col
);
438 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
441 gdk_gc_set_function( m_textGC
, GDK_COPY
);
442 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
443 gdk_gc_set_function( m_penGC
, GDK_COPY
);
446 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
447 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
448 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
449 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
453 hatch_bitmap
= hatches
;
454 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
455 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
456 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
457 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
458 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
459 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
463 void wxWindowDC::DoGetSize( int* width
, int* height
) const
465 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
467 m_owner
->GetSize(width
, height
);
470 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
471 const wxColour
& col
, int style
);
473 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
474 const wxColour
& col
, int style
)
476 return wxDoFloodFill(this, x
, y
, col
, style
);
479 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
481 // Generic (and therefore rather inefficient) method.
482 // Could be improved.
484 wxBitmap
bitmap(1, 1);
485 memdc
.SelectObject(bitmap
);
486 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
487 memdc
.SelectObject(wxNullBitmap
);
489 wxImage image
= bitmap
.ConvertToImage();
490 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
494 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
496 wxCHECK_RET( Ok(), wxT("invalid window dc") );
498 if (m_pen
.GetStyle() != wxTRANSPARENT
)
501 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
503 CalcBoundingBox(x1
, y1
);
504 CalcBoundingBox(x2
, y2
);
508 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
510 wxCHECK_RET( Ok(), wxT("invalid window dc") );
512 if (m_pen
.GetStyle() != wxTRANSPARENT
)
517 wxCoord xx
= XLOG2DEV(x
);
518 wxCoord yy
= YLOG2DEV(y
);
521 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
522 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
527 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
528 wxCoord xc
, wxCoord yc
)
530 wxCHECK_RET( Ok(), wxT("invalid window dc") );
532 wxCoord xx1
= XLOG2DEV(x1
);
533 wxCoord yy1
= YLOG2DEV(y1
);
534 wxCoord xx2
= XLOG2DEV(x2
);
535 wxCoord yy2
= YLOG2DEV(y2
);
536 wxCoord xxc
= XLOG2DEV(xc
);
537 wxCoord yyc
= YLOG2DEV(yc
);
538 double dx
= xx1
- xxc
;
539 double dy
= yy1
- yyc
;
540 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
541 wxCoord r
= (wxCoord
)radius
;
542 double radius1
, radius2
;
544 if (xx1
== xx2
&& yy1
== yy2
)
552 radius1
= radius2
= 0.0;
556 radius1
= (xx1
- xxc
== 0) ?
557 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
558 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
559 radius2
= (xx2
- xxc
== 0) ?
560 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
561 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
563 wxCoord alpha1
= wxCoord(radius1
* 64.0);
564 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
565 while (alpha2
<= 0) alpha2
+= 360*64;
566 while (alpha1
> 360*64) alpha1
-= 360*64;
570 if (m_brush
.GetStyle() != wxTRANSPARENT
)
572 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
574 gdk_gc_set_ts_origin( m_textGC
,
575 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
576 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
577 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
578 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
580 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
582 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
583 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
584 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
586 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
588 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
589 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
590 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
592 if (m_brush
.GetStyle() == wxSTIPPLE
)
594 gdk_gc_set_ts_origin( m_brushGC
,
595 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
596 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
597 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
598 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
602 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
606 if (m_pen
.GetStyle() != wxTRANSPARENT
)
608 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
610 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
611 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
615 CalcBoundingBox (x1
, y1
);
616 CalcBoundingBox (x2
, y2
);
619 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
621 wxCHECK_RET( Ok(), wxT("invalid window dc") );
623 wxCoord xx
= XLOG2DEV(x
);
624 wxCoord yy
= YLOG2DEV(y
);
625 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
626 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
628 // CMB: handle -ve width and/or height
629 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
630 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
634 wxCoord start
= wxCoord(sa
* 64.0);
635 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
637 if (m_brush
.GetStyle() != wxTRANSPARENT
)
639 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
641 gdk_gc_set_ts_origin( m_textGC
,
642 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
643 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
644 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
645 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
647 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
649 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
650 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
651 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
653 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
655 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
656 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
657 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
659 if (m_brush
.GetStyle() == wxSTIPPLE
)
661 gdk_gc_set_ts_origin( m_brushGC
,
662 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
663 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
664 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
665 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
669 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
673 if (m_pen
.GetStyle() != wxTRANSPARENT
)
674 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
677 CalcBoundingBox (x
, y
);
678 CalcBoundingBox (x
+ width
, y
+ height
);
681 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
683 wxCHECK_RET( Ok(), wxT("invalid window dc") );
685 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
686 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
688 CalcBoundingBox (x
, y
);
691 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
693 wxCHECK_RET( Ok(), wxT("invalid window dc") );
695 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
698 GdkPoint
*gpts
= new GdkPoint
[n
];
701 wxFAIL_MSG( wxT("Cannot allocate PolyLine") );
705 for (int i
= 0; i
< n
; i
++)
707 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
708 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
);
710 CalcBoundingBox( x1
+ xoffset
, y1
+ yoffset
);
717 gdk_draw_lines( m_window
, m_penGC
, gpts
, n
);
722 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
724 wxCHECK_RET( Ok(), wxT("invalid window dc") );
728 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
730 for (i
= 0 ; i
< n
; i
++)
732 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
733 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
735 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
740 if (m_brush
.GetStyle() != wxTRANSPARENT
)
742 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
744 gdk_gc_set_ts_origin( m_textGC
,
745 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
746 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
747 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
748 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
750 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
752 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
753 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
754 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
756 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
758 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
759 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
760 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
762 if (m_brush
.GetStyle() == wxSTIPPLE
)
764 gdk_gc_set_ts_origin( m_brushGC
,
765 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
766 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
767 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
768 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
772 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
776 if (m_pen
.GetStyle() != wxTRANSPARENT
)
778 for (i
= 0 ; i
< n
; i
++)
780 gdk_draw_line( m_window
, m_penGC
,
783 gdkpoints
[(i
+1)%n
].x
,
784 gdkpoints
[(i
+1)%n
].y
);
792 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
794 wxCHECK_RET( Ok(), wxT("invalid window dc") );
796 wxCoord xx
= XLOG2DEV(x
);
797 wxCoord yy
= YLOG2DEV(y
);
798 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
799 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
801 // CMB: draw nothing if transformed w or h is 0
802 if (ww
== 0 || hh
== 0) return;
804 // CMB: handle -ve width and/or height
805 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
806 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
810 if (m_brush
.GetStyle() != wxTRANSPARENT
)
812 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
814 gdk_gc_set_ts_origin( m_textGC
,
815 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
816 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
817 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
818 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
820 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
822 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
823 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
824 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
826 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
828 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
829 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
830 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
832 if (m_brush
.GetStyle() == wxSTIPPLE
)
834 gdk_gc_set_ts_origin( m_brushGC
,
835 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
836 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
837 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
838 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
842 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
846 if (m_pen
.GetStyle() != wxTRANSPARENT
)
847 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
850 CalcBoundingBox( x
, y
);
851 CalcBoundingBox( x
+ width
, y
+ height
);
854 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
856 wxCHECK_RET( Ok(), wxT("invalid window dc") );
858 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
860 wxCoord xx
= XLOG2DEV(x
);
861 wxCoord yy
= YLOG2DEV(y
);
862 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
863 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
864 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
866 // CMB: handle -ve width and/or height
867 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
868 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
870 // CMB: if radius is zero use DrawRectangle() instead to avoid
871 // X drawing errors with small radii
874 DrawRectangle( x
, y
, width
, height
);
878 // CMB: draw nothing if transformed w or h is 0
879 if (ww
== 0 || hh
== 0) return;
881 // CMB: adjust size if outline is drawn otherwise the result is
882 // 1 pixel too wide and high
883 if (m_pen
.GetStyle() != wxTRANSPARENT
)
891 // CMB: ensure dd is not larger than rectangle otherwise we
892 // get an hour glass shape
894 if (dd
> ww
) dd
= ww
;
895 if (dd
> hh
) dd
= hh
;
898 if (m_brush
.GetStyle() != wxTRANSPARENT
)
900 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
902 gdk_gc_set_ts_origin( m_textGC
,
903 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
904 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
905 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
906 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
907 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
908 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
909 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
910 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
911 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
913 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
915 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
916 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
917 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
918 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
919 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
920 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
921 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
922 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
924 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
926 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
927 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
928 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
929 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
930 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
931 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
932 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
933 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
935 if (m_brush
.GetStyle() == wxSTIPPLE
)
937 gdk_gc_set_ts_origin( m_brushGC
,
938 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
939 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
940 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
941 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
942 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
943 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
944 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
945 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
946 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
950 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
951 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
952 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
953 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
954 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
955 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
959 if (m_pen
.GetStyle() != wxTRANSPARENT
)
961 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
962 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
963 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
964 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
965 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
966 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
967 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
968 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
972 // this ignores the radius
973 CalcBoundingBox( x
, y
);
974 CalcBoundingBox( x
+ width
, y
+ height
);
977 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
979 wxCHECK_RET( Ok(), wxT("invalid window dc") );
981 wxCoord xx
= XLOG2DEV(x
);
982 wxCoord yy
= YLOG2DEV(y
);
983 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
984 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
986 // CMB: handle -ve width and/or height
987 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
988 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
992 if (m_brush
.GetStyle() != wxTRANSPARENT
)
994 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
996 gdk_gc_set_ts_origin( m_textGC
,
997 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
998 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
999 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1000 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
1002 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
1004 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
1005 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1006 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1008 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
1010 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
1011 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1012 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1014 if (m_brush
.GetStyle() == wxSTIPPLE
)
1016 gdk_gc_set_ts_origin( m_brushGC
,
1017 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1018 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1019 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1020 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1024 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1028 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1029 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1032 CalcBoundingBox( x
, y
);
1033 CalcBoundingBox( x
+ width
, y
+ height
);
1036 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1038 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1039 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1042 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1043 wxCoord x
, wxCoord y
,
1046 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1048 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1050 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1052 /* scale/translate size and position */
1053 int xx
= XLOG2DEV(x
);
1054 int yy
= YLOG2DEV(y
);
1056 int w
= bitmap
.GetWidth();
1057 int h
= bitmap
.GetHeight();
1059 CalcBoundingBox( x
, y
);
1060 CalcBoundingBox( x
+ w
, y
+ h
);
1062 if (!m_window
) return;
1064 int ww
= XLOG2DEVREL(w
);
1065 int hh
= YLOG2DEVREL(h
);
1067 /* compare to current clipping region */
1068 if (!m_currentClippingRegion
.IsNull())
1070 wxRegion
tmp( xx
,yy
,ww
,hh
);
1071 tmp
.Intersect( m_currentClippingRegion
);
1076 /* scale bitmap if required */
1077 wxBitmap use_bitmap
;
1078 if ((w
!= ww
) || (h
!= hh
))
1080 wxImage image
= bitmap
.ConvertToImage();
1081 image
.Rescale( ww
, hh
);
1083 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1085 use_bitmap
= wxBitmap(image
);
1089 use_bitmap
= bitmap
;
1092 /* apply mask if any */
1093 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1094 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1096 if (useMask
&& mask
)
1098 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1099 #ifndef __WXGTK20__ // TODO fix crash
1100 if (!m_currentClippingRegion
.IsNull())
1103 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1104 GdkGC
*gc
= gdk_gc_new( new_mask
);
1106 gdk_gc_set_foreground( gc
, &col
);
1107 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1109 gdk_gc_set_background( gc
, &col
);
1111 gdk_gc_set_foreground( gc
, &col
);
1112 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1113 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1114 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1115 gdk_gc_set_stipple( gc
, mask
);
1116 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1123 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1125 gdk_gc_set_clip_mask( m_textGC
, mask
);
1126 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1131 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1133 gdk_gc_set_clip_mask( m_penGC
, mask
);
1134 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1138 gdk_bitmap_unref( new_mask
);
1141 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1142 drawing a mono-bitmap (XBitmap) we use the current text GC */
1144 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1146 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1148 /* remove mask again if any */
1149 if (useMask
&& mask
)
1153 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1154 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1155 if (!m_currentClippingRegion
.IsNull())
1156 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1160 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1161 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1162 if (!m_currentClippingRegion
.IsNull())
1163 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1168 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1169 wxCoord width
, wxCoord height
,
1171 wxCoord xsrc
, wxCoord ysrc
,
1174 wxCoord xsrcMask
, wxCoord ysrcMask
)
1176 /* this is the nth try to get this utterly useless function to
1177 work. it now completely ignores the scaling or translation
1178 of the source dc, but scales correctly on the target dc and
1179 knows about possible mask information in a memory dc. */
1181 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1183 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1185 if (!m_window
) return FALSE
;
1188 // transform the source DC coords to the device ones
1189 xsrc
= source
->XLOG2DEV(xsrc
);
1190 ysrc
= source
->YLOG2DEV(ysrc
);
1193 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1194 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1196 bool use_bitmap_method
= FALSE
;
1197 bool is_mono
= FALSE
;
1199 /* TODO: use the mask origin when drawing transparently */
1200 if (xsrcMask
== -1 && ysrcMask
== -1)
1202 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1205 if (srcDC
->m_isMemDC
)
1207 if (!memDC
->m_selected
.Ok()) return FALSE
;
1209 /* we use the "XCopyArea" way to copy a memory dc into
1210 y different window if the memory dc BOTH
1211 a) doesn't have any mask or its mask isn't used
1215 if (useMask
&& (memDC
->m_selected
.GetMask()))
1217 /* we HAVE TO use the direct way for memory dcs
1218 that have mask since the XCopyArea doesn't know
1220 use_bitmap_method
= TRUE
;
1222 else if (memDC
->m_selected
.GetDepth() == 1)
1224 /* we HAVE TO use the direct way for memory dcs
1225 that are bitmaps because XCopyArea doesn't cope
1226 with different bit depths */
1228 use_bitmap_method
= TRUE
;
1230 else if ((xsrc
== 0) && (ysrc
== 0) &&
1231 (width
== memDC
->m_selected
.GetWidth()) &&
1232 (height
== memDC
->m_selected
.GetHeight()))
1234 /* we SHOULD use the direct way if all of the bitmap
1235 in the memory dc is copied in which case XCopyArea
1236 wouldn't be able able to boost performace by reducing
1237 the area to be scaled */
1238 use_bitmap_method
= TRUE
;
1242 use_bitmap_method
= FALSE
;
1246 CalcBoundingBox( xdest
, ydest
);
1247 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1249 /* scale/translate size and position */
1250 wxCoord xx
= XLOG2DEV(xdest
);
1251 wxCoord yy
= YLOG2DEV(ydest
);
1253 wxCoord ww
= XLOG2DEVREL(width
);
1254 wxCoord hh
= YLOG2DEVREL(height
);
1256 /* compare to current clipping region */
1257 if (!m_currentClippingRegion
.IsNull())
1259 wxRegion
tmp( xx
,yy
,ww
,hh
);
1260 tmp
.Intersect( m_currentClippingRegion
);
1265 int old_logical_func
= m_logicalFunction
;
1266 SetLogicalFunction( logical_func
);
1268 if (use_bitmap_method
)
1270 /* scale/translate bitmap size */
1271 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1272 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1274 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1275 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1277 /* scale bitmap if required */
1278 wxBitmap use_bitmap
;
1280 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1282 wxImage image
= memDC
->m_selected
.ConvertToImage();
1283 image
= image
.Scale( bm_ww
, bm_hh
);
1286 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1288 use_bitmap
= wxBitmap(image
);
1292 use_bitmap
= memDC
->m_selected
;
1295 /* apply mask if any */
1296 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1297 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1299 if (useMask
&& mask
)
1301 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1302 #ifndef __WXGTK20__ // TODO fix crash
1303 if (!m_currentClippingRegion
.IsNull())
1306 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1307 GdkGC
*gc
= gdk_gc_new( new_mask
);
1309 gdk_gc_set_foreground( gc
, &col
);
1310 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1312 gdk_gc_set_background( gc
, &col
);
1314 gdk_gc_set_foreground( gc
, &col
);
1315 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1316 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1317 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1318 gdk_gc_set_stipple( gc
, mask
);
1319 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1326 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1328 gdk_gc_set_clip_mask( m_textGC
, mask
);
1329 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1334 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1336 gdk_gc_set_clip_mask( m_penGC
, mask
);
1337 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1340 gdk_bitmap_unref( new_mask
);
1343 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1344 drawing a mono-bitmap (XBitmap) we use the current text GC */
1347 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1349 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1351 /* remove mask again if any */
1352 if (useMask
&& mask
)
1356 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1357 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1358 if (!m_currentClippingRegion
.IsNull())
1359 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1363 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1364 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1365 if (!m_currentClippingRegion
.IsNull())
1366 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1370 else /* use_bitmap_method */
1372 if ((width
!= ww
) || (height
!= hh
))
1374 /* draw source window into a bitmap as we cannot scale
1375 a window in contrast to a bitmap. this would actually
1376 work with memory dcs as well, but we'd lose the mask
1377 information and waste one step in this process since
1378 a memory already has a bitmap. all this is slightly
1379 inefficient as we could take an XImage directly from
1380 an X window, but we'd then also have to care that
1381 the window is not outside the screen (in which case
1382 we'd get a BadMatch or what not).
1383 Is a double XGetImage and combined XGetPixel and
1384 XPutPixel really faster? I'm not sure. look at wxXt
1385 for a different implementation of the same problem. */
1387 wxBitmap
bitmap( width
, height
);
1389 /* copy including child window contents */
1390 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1391 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1393 xsrc
, ysrc
, width
, height
);
1394 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1397 wxImage image
= bitmap
.ConvertToImage();
1398 image
= image
.Scale( ww
, hh
);
1400 /* convert to bitmap */
1401 bitmap
= wxBitmap(image
);
1403 /* draw scaled bitmap */
1404 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1409 /* No scaling and not a memory dc with a mask either */
1411 /* copy including child window contents */
1412 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1413 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1415 xsrc
, ysrc
, width
, height
);
1416 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1420 SetLogicalFunction( old_logical_func
);
1424 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1426 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1428 if (!m_window
) return;
1430 if (text
.empty()) return;
1433 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1435 wxCHECK_RET( font
, wxT("invalid font") );
1442 wxCHECK_RET( m_context
, wxT("no Pango context") );
1443 wxCHECK_RET( m_layout
, wxT("no Pango layout") );
1444 wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") );
1447 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
1449 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( text
);
1450 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1452 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1454 if (m_scaleY
!= 1.0)
1456 // If there is a user or actually any scale applied to
1457 // the device context, scale the font.
1459 // scale font description
1460 gint oldSize
= pango_font_description_get_size( m_fontdesc
);
1461 double size
= oldSize
;
1462 size
= size
* m_scaleY
;
1463 pango_font_description_set_size( m_fontdesc
, (gint
)size
);
1465 // actually apply scaled font
1466 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1469 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1471 // reset unscaled size
1472 pango_font_description_set_size( m_fontdesc
, oldSize
);
1474 // actually apply unscaled font
1475 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1480 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1486 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1496 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1497 wxCoord height
= font
->ascent
+ font
->descent
;
1499 if ( m_backgroundMode
== wxSOLID
)
1501 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1502 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1503 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1505 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1507 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1508 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1509 properties (see wxXt implementation) */
1510 if (m_font
.GetUnderlined())
1512 wxCoord ul_y
= y
+ font
->ascent
;
1513 if (font
->descent
> 0) ul_y
++;
1514 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1516 #endif // GTK+ 2.0/1.x
1518 width
= wxCoord(width
/ m_scaleX
);
1519 height
= wxCoord(height
/ m_scaleY
);
1520 CalcBoundingBox (x
+ width
, y
+ height
);
1521 CalcBoundingBox (x
, y
);
1524 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1528 DrawText(text
, x
, y
);
1532 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1534 if (!m_window
) return;
1537 // implement later without GdkFont for GTK 2.0
1540 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1542 wxCHECK_RET( font
, wxT("invalid font") );
1544 // the size of the text
1545 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1546 wxCoord h
= font
->ascent
+ font
->descent
;
1548 // draw the string normally
1551 dc
.SelectObject(src
);
1552 dc
.SetFont(GetFont());
1553 dc
.SetBackground(*wxWHITE_BRUSH
);
1554 dc
.SetBrush(*wxBLACK_BRUSH
);
1556 dc
.DrawText(text
, 0, 0);
1557 dc
.SelectObject(wxNullBitmap
);
1559 // Calculate the size of the rotated bounding box.
1560 double rad
= DegToRad(angle
);
1561 double dx
= cos(rad
),
1564 // the rectngle vertices are counted clockwise with the first one being at
1565 // (0, 0) (or, rather, at (x, y))
1567 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1570 double x3
= x4
+ x2
,
1574 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1575 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1576 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1577 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1579 // prepare to blit-with-rotate the bitmap to the DC
1580 wxImage image
= src
.ConvertToImage();
1582 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1583 *colBack
= m_textBackgroundColour
.GetColor();
1585 bool textColSet
= TRUE
;
1587 unsigned char *data
= image
.GetData();
1589 // paint pixel by pixel
1590 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1592 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1594 // transform source coords to dest coords
1595 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1596 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1597 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1598 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1601 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1602 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1604 // change colour if needed
1605 if ( textPixel
!= textColSet
)
1607 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1610 textColSet
= textPixel
;
1613 // don't use DrawPoint() because it uses the current pen
1614 // colour, and we don't need it here
1615 gdk_draw_point( m_window
, m_textGC
,
1616 XLOG2DEV(x
) + dstX
, YLOG2DEV(y
) + dstY
);
1621 // it would be better to draw with non underlined font and draw the line
1622 // manually here (it would be more straight...)
1624 if ( m_font
.GetUnderlined() )
1626 gdk_draw_line( m_window
, m_textGC
,
1627 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1628 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1632 // restore the font colour
1633 gdk_gc_set_foreground( m_textGC
, colText
);
1635 // update the bounding box
1636 CalcBoundingBox(x
+ minX
, y
+ minY
);
1637 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1641 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1642 wxCoord
*width
, wxCoord
*height
,
1643 wxCoord
*descent
, wxCoord
*externalLeading
,
1644 wxFont
*theFont
) const
1646 if (string
.IsEmpty())
1648 if (width
) (*width
) = 0;
1649 if (height
) (*height
) = 0;
1654 // Set new font description
1656 pango_layout_set_font_description( m_layout
, theFont
->GetNativeFontInfo()->description
);
1658 // Set layout's text
1660 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
1661 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1663 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( string
);
1664 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1665 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1669 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1671 if (width
) (*width
) = (wxCoord
) w
;
1672 if (height
) (*height
) = (wxCoord
) h
;
1675 // Do something about metrics here. TODO.
1678 if (externalLeading
) (*externalLeading
) = 0; // ??
1680 // Reset old font description
1682 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1684 wxFont fontToUse
= m_font
;
1685 if (theFont
) fontToUse
= *theFont
;
1687 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1688 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1689 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1690 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1691 if (externalLeading
) (*externalLeading
) = 0; // ??
1695 wxCoord
wxWindowDC::GetCharWidth() const
1698 pango_layout_set_text( m_layout
, "H", 1 );
1700 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1703 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1704 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1706 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1710 wxCoord
wxWindowDC::GetCharHeight() const
1713 pango_layout_set_text( m_layout
, "H", 1 );
1715 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1718 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1719 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1721 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1725 void wxWindowDC::Clear()
1727 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1729 if (!m_window
) return;
1731 // VZ: the code below results in infinite recursion and crashes when
1732 // dc.Clear() is done from OnPaint() so I disable it for now.
1733 // I don't know what the correct fix is but Clear() surely should not
1734 // reenter OnPaint()!
1736 /* - we either are a memory dc or have a window as the
1737 owner. anything else shouldn't happen.
1738 - we don't use gdk_window_clear() as we don't set
1739 the window's background colour anymore. it is too
1740 much pain to keep the DC's and the window's back-
1741 ground colour in synch. */
1752 GetSize( &width
, &height
);
1753 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1758 GetSize( &width
, &height
);
1759 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1763 void wxWindowDC::SetFont( const wxFont
&font
)
1771 pango_font_description_free( m_fontdesc
);
1773 m_fontdesc
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description
);
1778 PangoContext
*oldContext
= m_context
;
1780 // We might want to use the X11 context for faster
1781 // rendering on screen
1782 if (m_font
.GetNoAntiAliasing())
1783 m_context
= m_owner
->GtkGetPangoX11Context();
1785 m_context
= m_owner
->GtkGetPangoDefaultContext();
1787 // If we switch back/forth between different contexts
1788 // we also have to create a new layout. I think so,
1789 // at least, and it doesn't hurt to do it.
1790 if (oldContext
!= m_context
)
1793 g_object_unref( G_OBJECT( m_layout
) );
1795 m_layout
= pango_layout_new( m_context
);
1799 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1804 void wxWindowDC::SetPen( const wxPen
&pen
)
1806 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1808 if (m_pen
== pen
) return;
1812 if (!m_pen
.Ok()) return;
1814 if (!m_window
) return;
1816 gint width
= m_pen
.GetWidth();
1819 // CMB: if width is non-zero scale it with the dc
1824 // X doesn't allow different width in x and y and so we take
1827 ( fabs((double) XLOG2DEVREL(width
)) +
1828 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1832 static const wxGTKDash dotted
[] = {1, 1};
1833 static const wxGTKDash short_dashed
[] = {2, 2};
1834 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1835 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1837 // We express dash pattern in pen width unit, so we are
1838 // independent of zoom factor and so on...
1840 const wxGTKDash
*req_dash
;
1842 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1843 switch (m_pen
.GetStyle())
1847 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1848 req_nb_dash
= m_pen
.GetDashCount();
1849 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1854 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1861 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1863 req_dash
= wxCoord_dashed
;
1868 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1870 req_dash
= short_dashed
;
1875 // lineStyle = GDK_LINE_DOUBLE_DASH;
1876 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1878 req_dash
= dotted_dashed
;
1883 case wxSTIPPLE_MASK_OPAQUE
:
1888 lineStyle
= GDK_LINE_SOLID
;
1889 req_dash
= (wxGTKDash
*)NULL
;
1895 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1896 if (req_dash
&& req_nb_dash
)
1898 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1901 for (int i
= 0; i
< req_nb_dash
; i
++)
1902 real_req_dash
[i
] = req_dash
[i
] * width
;
1903 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1904 delete[] real_req_dash
;
1908 // No Memory. We use non-scaled dash pattern...
1909 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1912 #endif // GTK+ > 1.0
1914 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1915 switch (m_pen
.GetCap())
1917 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1918 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1925 capStyle
= GDK_CAP_NOT_LAST
;
1929 capStyle
= GDK_CAP_ROUND
;
1935 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1936 switch (m_pen
.GetJoin())
1938 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1939 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1941 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1944 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1946 m_pen
.GetColour().CalcPixel( m_cmap
);
1947 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1950 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1952 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1954 if (m_brush
== brush
) return;
1958 if (!m_brush
.Ok()) return;
1960 if (!m_window
) return;
1962 m_brush
.GetColour().CalcPixel( m_cmap
);
1963 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1965 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1967 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1969 if (m_brush
.GetStipple()->GetPixmap())
1971 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1972 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1976 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1977 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1981 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1983 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1984 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1987 if (IS_HATCH(m_brush
.GetStyle()))
1989 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1990 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1991 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1995 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1997 /* CMB 21/7/98: Added SetBackground. Sets background brush
1998 * for Clear() and bg colour for shapes filled with cross-hatch brush */
2000 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2002 if (m_backgroundBrush
== brush
) return;
2004 m_backgroundBrush
= brush
;
2006 if (!m_backgroundBrush
.Ok()) return;
2008 if (!m_window
) return;
2010 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
2011 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
2012 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
2013 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2014 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2016 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
2018 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
2020 if (m_backgroundBrush
.GetStipple()->GetPixmap())
2022 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
2023 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
2027 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2028 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
2032 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
2034 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2035 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
2036 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
2040 void wxWindowDC::SetLogicalFunction( int function
)
2042 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2044 if (m_logicalFunction
== function
)
2047 // VZ: shouldn't this be a CHECK?
2054 case wxXOR
: mode
= GDK_XOR
; break;
2055 case wxINVERT
: mode
= GDK_INVERT
; break;
2056 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
2057 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
2058 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
2059 case wxCLEAR
: mode
= GDK_CLEAR
; break;
2060 case wxSET
: mode
= GDK_SET
; break;
2061 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
2062 case wxAND
: mode
= GDK_AND
; break;
2063 case wxOR
: mode
= GDK_OR
; break;
2064 case wxEQUIV
: mode
= GDK_EQUIV
; break;
2065 case wxNAND
: mode
= GDK_NAND
; break;
2066 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
2067 case wxCOPY
: mode
= GDK_COPY
; break;
2068 case wxNO_OP
: mode
= GDK_NOOP
; break;
2069 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
2071 // unsupported by GTK
2072 case wxNOR
: mode
= GDK_COPY
; break;
2073 #endif // GTK+ > 1.0
2075 wxFAIL_MSG( wxT("unsupported logical function") );
2079 m_logicalFunction
= function
;
2081 gdk_gc_set_function( m_penGC
, mode
);
2082 gdk_gc_set_function( m_brushGC
, mode
);
2084 // to stay compatible with wxMSW, we don't apply ROPs to the text
2085 // operations (i.e. DrawText/DrawRotatedText).
2086 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2087 gdk_gc_set_function( m_textGC
, mode
);
2090 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2092 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2094 // don't set m_textForegroundColour to an invalid colour as we'd crash
2095 // later then (we use m_textForegroundColour.GetColor() without checking
2097 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
2100 m_textForegroundColour
= col
;
2104 m_textForegroundColour
.CalcPixel( m_cmap
);
2105 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
2109 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2111 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2114 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
2117 m_textBackgroundColour
= col
;
2121 m_textBackgroundColour
.CalcPixel( m_cmap
);
2122 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
2126 void wxWindowDC::SetBackgroundMode( int mode
)
2128 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2130 m_backgroundMode
= mode
;
2132 if (!m_window
) return;
2134 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2135 // transparent/solid background mode
2137 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2139 gdk_gc_set_fill( m_brushGC
,
2140 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2144 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2146 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2149 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2151 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2153 if (!m_window
) return;
2156 rect
.x
= XLOG2DEV(x
);
2157 rect
.y
= YLOG2DEV(y
);
2158 rect
.width
= XLOG2DEVREL(width
);
2159 rect
.height
= YLOG2DEVREL(height
);
2161 if (!m_currentClippingRegion
.IsNull())
2162 m_currentClippingRegion
.Intersect( rect
);
2164 m_currentClippingRegion
.Union( rect
);
2166 #if USE_PAINT_REGION
2167 if (!m_paintClippingRegion
.IsNull())
2168 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2171 wxCoord xx
, yy
, ww
, hh
;
2172 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2173 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2175 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2176 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2177 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2178 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2181 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2183 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2187 DestroyClippingRegion();
2191 if (!m_window
) return;
2193 if (!m_currentClippingRegion
.IsNull())
2194 m_currentClippingRegion
.Intersect( region
);
2196 m_currentClippingRegion
.Union( region
);
2198 #if USE_PAINT_REGION
2199 if (!m_paintClippingRegion
.IsNull())
2200 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2203 wxCoord xx
, yy
, ww
, hh
;
2204 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2205 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2207 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2208 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2209 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2210 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2213 void wxWindowDC::DestroyClippingRegion()
2215 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2217 wxDC::DestroyClippingRegion();
2219 m_currentClippingRegion
.Clear();
2221 #if USE_PAINT_REGION
2222 if (!m_paintClippingRegion
.IsEmpty())
2223 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2226 if (!m_window
) return;
2228 if (m_currentClippingRegion
.IsEmpty())
2230 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2231 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2232 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2233 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2237 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2238 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2239 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2240 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2244 void wxWindowDC::Destroy()
2246 if (m_penGC
) wxFreePoolGC( m_penGC
);
2247 m_penGC
= (GdkGC
*) NULL
;
2248 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2249 m_brushGC
= (GdkGC
*) NULL
;
2250 if (m_textGC
) wxFreePoolGC( m_textGC
);
2251 m_textGC
= (GdkGC
*) NULL
;
2252 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2253 m_bgGC
= (GdkGC
*) NULL
;
2256 void wxWindowDC::ComputeScaleAndOrigin()
2258 /* CMB: copy scale to see if it changes */
2259 double origScaleX
= m_scaleX
;
2260 double origScaleY
= m_scaleY
;
2262 wxDC::ComputeScaleAndOrigin();
2264 /* CMB: if scale has changed call SetPen to recalulate the line width */
2265 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2268 /* this is a bit artificial, but we need to force wxDC to think
2269 the pen has changed */
2276 // Resolution in pixels per logical inch
2277 wxSize
wxWindowDC::GetPPI() const
2279 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2282 int wxWindowDC::GetDepth() const
2284 wxFAIL_MSG(wxT("not implemented"));
2290 //-----------------------------------------------------------------------------
2292 //-----------------------------------------------------------------------------
2294 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2296 wxPaintDC::wxPaintDC( wxWindow
*win
)
2299 #if USE_PAINT_REGION
2300 if (!win
->m_clipPaintRegion
)
2303 m_paintClippingRegion
= win
->GetUpdateRegion();
2304 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2307 m_paintClippingRegion
= win
->GetUpdateRegion();
2308 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2311 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2313 gdk_gc_set_clip_region( m_penGC
, region
);
2314 gdk_gc_set_clip_region( m_brushGC
, region
);
2315 gdk_gc_set_clip_region( m_textGC
, region
);
2316 gdk_gc_set_clip_region( m_bgGC
, region
);
2319 #endif // USE_PAINT_REGION
2322 //-----------------------------------------------------------------------------
2324 //-----------------------------------------------------------------------------
2326 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2328 wxClientDC::wxClientDC( wxWindow
*win
)
2331 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2333 #ifdef __WXUNIVERSAL__
2334 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2335 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2336 wxSize size
= win
->GetClientSize();
2337 SetClippingRegion(wxPoint(0, 0), size
);
2338 #endif // __WXUNIVERSAL__
2341 void wxClientDC::DoGetSize(int *width
, int *height
) const
2343 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2345 m_owner
->GetClientSize( width
, height
);
2348 // ----------------------------------------------------------------------------
2350 // ----------------------------------------------------------------------------
2352 class wxDCModule
: public wxModule
2359 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2362 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2364 bool wxDCModule::OnInit()
2370 void wxDCModule::OnExit()