]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk1/dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/dcclient.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "dcclient.h"
15 #define XCopyPlane XCOPYPLANE
18 #include "wx/dcclient.h"
19 #include "wx/dcmemory.h"
21 #include "wx/module.h"
23 #include "wx/fontutil.h"
25 #include "wx/gtk/win_gtk.h"
27 #include <math.h> // for floating-point functions
31 #include <gdk/gdkprivate.h>
34 //-----------------------------------------------------------------------------
36 //-----------------------------------------------------------------------------
38 #define USE_PAINT_REGION 1
40 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
52 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
53 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
56 static GdkPixmap
*hatches
[num_hatches
];
57 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
59 extern GtkWidget
*wxGetRootWindow();
61 //-----------------------------------------------------------------------------
63 //-----------------------------------------------------------------------------
65 const double RAD2DEG
= 180.0 / M_PI
;
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
72 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
74 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
76 //-----------------------------------------------------------------------------
77 // temporary implementation of the missing GDK function
78 //-----------------------------------------------------------------------------
80 #include "gdk/gdkprivate.h"
82 void gdk_wx_draw_bitmap(GdkDrawable
*drawable
,
92 gint src_width
, src_height
;
94 GdkWindowPrivate
*drawable_private
;
95 GdkWindowPrivate
*src_private
;
96 GdkGCPrivate
*gc_private
;
99 g_return_if_fail (drawable
!= NULL
);
100 g_return_if_fail (src
!= NULL
);
101 g_return_if_fail (gc
!= NULL
);
104 if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
))
107 gdk_drawable_get_size(src
, &src_width
, &src_height
);
109 drawable_private
= (GdkWindowPrivate
*) drawable
;
110 src_private
= (GdkWindowPrivate
*) src
;
111 if (drawable_private
->destroyed
|| src_private
->destroyed
)
114 src_width
= src_private
->width
;
115 src_height
= src_private
->height
;
117 gc_private
= (GdkGCPrivate
*) gc
;
120 if (width
== -1) width
= src_width
;
121 if (height
== -1) height
= src_height
;
124 XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
),
126 GDK_WINDOW_XID(drawable
),
133 XCopyPlane( drawable_private
->xdisplay
,
134 src_private
->xwindow
,
135 drawable_private
->xwindow
,
144 //-----------------------------------------------------------------------------
145 // Implement Pool of Graphic contexts. Creating them takes too much time.
146 //-----------------------------------------------------------------------------
148 #define GC_POOL_SIZE 200
174 #define GC_POOL_ALLOC_SIZE 100
176 static int wxGCPoolSize
= 0;
178 static wxGC
*wxGCPool
= NULL
;
180 static void wxInitGCPool()
182 // This really could wait until the first call to
183 // wxGetPoolGC, but we will make the first allocation
184 // now when other initialization is being performed.
186 // Set initial pool size.
187 wxGCPoolSize
= GC_POOL_ALLOC_SIZE
;
189 // Allocate initial pool.
190 wxGCPool
= (wxGC
*)malloc(wxGCPoolSize
* sizeof(wxGC
));
191 if (wxGCPool
== NULL
)
193 // If we cannot malloc, then fail with error
194 // when debug is enabled. If debug is not enabled,
195 // the problem will eventually get caught
197 wxFAIL_MSG( wxT("Cannot allocate GC pool") );
201 // Zero initial pool.
202 memset(wxGCPool
, 0, wxGCPoolSize
* sizeof(wxGC
));
205 static void wxCleanUpGCPool()
207 for (int i
= 0; i
< wxGCPoolSize
; i
++)
209 if (wxGCPool
[i
].m_gc
)
210 gdk_gc_unref( wxGCPool
[i
].m_gc
);
218 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
222 // Look for an available GC.
223 for (int i
= 0; i
< wxGCPoolSize
; i
++)
225 if (!wxGCPool
[i
].m_gc
)
227 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
228 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
229 wxGCPool
[i
].m_type
= type
;
230 wxGCPool
[i
].m_used
= FALSE
;
232 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
234 wxGCPool
[i
].m_used
= TRUE
;
235 return wxGCPool
[i
].m_gc
;
239 // We did not find an available GC.
240 // We need to grow the GC pool.
241 pptr
= (wxGC
*)realloc(wxGCPool
,
242 (wxGCPoolSize
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
));
245 // Initialize newly allocated pool.
247 memset(&wxGCPool
[wxGCPoolSize
], 0,
248 GC_POOL_ALLOC_SIZE
*sizeof(wxGC
));
250 // Initialize entry we will return.
251 wxGCPool
[wxGCPoolSize
].m_gc
= gdk_gc_new( window
);
252 gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE
);
253 wxGCPool
[wxGCPoolSize
].m_type
= type
;
254 wxGCPool
[wxGCPoolSize
].m_used
= TRUE
;
256 // Set new value of pool size.
257 wxGCPoolSize
+= GC_POOL_ALLOC_SIZE
;
259 // Return newly allocated entry.
260 return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
;
263 // The realloc failed. Fall through to error.
264 wxFAIL_MSG( wxT("No GC available") );
266 return (GdkGC
*) NULL
;
269 static void wxFreePoolGC( GdkGC
*gc
)
271 for (int i
= 0; i
< wxGCPoolSize
; i
++)
273 if (wxGCPool
[i
].m_gc
== gc
)
275 wxGCPool
[i
].m_used
= FALSE
;
280 wxFAIL_MSG( wxT("Wrong GC") );
283 //-----------------------------------------------------------------------------
285 //-----------------------------------------------------------------------------
287 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
289 wxWindowDC::wxWindowDC()
291 m_penGC
= (GdkGC
*) NULL
;
292 m_brushGC
= (GdkGC
*) NULL
;
293 m_textGC
= (GdkGC
*) NULL
;
294 m_bgGC
= (GdkGC
*) NULL
;
295 m_cmap
= (GdkColormap
*) NULL
;
297 m_isScreenDC
= FALSE
;
298 m_owner
= (wxWindow
*)NULL
;
300 m_context
= (PangoContext
*)NULL
;
301 m_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 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
700 for (int i
= 0; i
< n
-1; i
++)
702 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
703 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
704 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
705 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
708 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
710 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
714 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
716 wxCHECK_RET( Ok(), wxT("invalid window dc") );
720 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
722 for (i
= 0 ; i
< n
; i
++)
724 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
725 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
727 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
732 if (m_brush
.GetStyle() != wxTRANSPARENT
)
734 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
736 gdk_gc_set_ts_origin( m_textGC
,
737 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
738 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
739 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
740 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
742 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
744 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
745 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
746 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
748 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
750 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
751 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
752 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
754 if (m_brush
.GetStyle() == wxSTIPPLE
)
756 gdk_gc_set_ts_origin( m_brushGC
,
757 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
758 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
759 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
760 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
764 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
768 if (m_pen
.GetStyle() != wxTRANSPARENT
)
770 for (i
= 0 ; i
< n
; i
++)
772 gdk_draw_line( m_window
, m_penGC
,
775 gdkpoints
[(i
+1)%n
].x
,
776 gdkpoints
[(i
+1)%n
].y
);
784 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
786 wxCHECK_RET( Ok(), wxT("invalid window dc") );
788 wxCoord xx
= XLOG2DEV(x
);
789 wxCoord yy
= YLOG2DEV(y
);
790 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
791 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
793 // CMB: draw nothing if transformed w or h is 0
794 if (ww
== 0 || hh
== 0) return;
796 // CMB: handle -ve width and/or height
797 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
798 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
802 if (m_brush
.GetStyle() != wxTRANSPARENT
)
804 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
806 gdk_gc_set_ts_origin( m_textGC
,
807 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
808 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
809 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
810 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
812 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
814 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
815 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
816 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
818 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
820 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
821 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
822 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
824 if (m_brush
.GetStyle() == wxSTIPPLE
)
826 gdk_gc_set_ts_origin( m_brushGC
,
827 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
828 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
829 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
830 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
834 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
838 if (m_pen
.GetStyle() != wxTRANSPARENT
)
839 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
842 CalcBoundingBox( x
, y
);
843 CalcBoundingBox( x
+ width
, y
+ height
);
846 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
848 wxCHECK_RET( Ok(), wxT("invalid window dc") );
850 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
852 wxCoord xx
= XLOG2DEV(x
);
853 wxCoord yy
= YLOG2DEV(y
);
854 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
855 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
856 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
858 // CMB: handle -ve width and/or height
859 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
860 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
862 // CMB: if radius is zero use DrawRectangle() instead to avoid
863 // X drawing errors with small radii
866 DrawRectangle( x
, y
, width
, height
);
870 // CMB: draw nothing if transformed w or h is 0
871 if (ww
== 0 || hh
== 0) return;
873 // CMB: adjust size if outline is drawn otherwise the result is
874 // 1 pixel too wide and high
875 if (m_pen
.GetStyle() != wxTRANSPARENT
)
883 // CMB: ensure dd is not larger than rectangle otherwise we
884 // get an hour glass shape
886 if (dd
> ww
) dd
= ww
;
887 if (dd
> hh
) dd
= hh
;
890 if (m_brush
.GetStyle() != wxTRANSPARENT
)
892 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
894 gdk_gc_set_ts_origin( m_textGC
,
895 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
896 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
897 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
898 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
899 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
900 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
901 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
902 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
903 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
905 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
907 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
908 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
909 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
910 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
911 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
912 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
913 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
914 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
916 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
918 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
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 (m_brush
.GetStyle() == wxSTIPPLE
)
929 gdk_gc_set_ts_origin( m_brushGC
,
930 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
931 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
932 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
933 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
934 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
935 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
936 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
937 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
938 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
942 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
943 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
944 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
945 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
946 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
947 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
951 if (m_pen
.GetStyle() != wxTRANSPARENT
)
953 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
954 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
955 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
956 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
957 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
958 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
959 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
960 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
964 // this ignores the radius
965 CalcBoundingBox( x
, y
);
966 CalcBoundingBox( x
+ width
, y
+ height
);
969 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
971 wxCHECK_RET( Ok(), wxT("invalid window dc") );
973 wxCoord xx
= XLOG2DEV(x
);
974 wxCoord yy
= YLOG2DEV(y
);
975 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
976 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
978 // CMB: handle -ve width and/or height
979 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
980 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
984 if (m_brush
.GetStyle() != wxTRANSPARENT
)
986 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
988 gdk_gc_set_ts_origin( m_textGC
,
989 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
990 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
991 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
992 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
994 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
996 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
997 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
998 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1000 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
1002 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
1003 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1004 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1006 if (m_brush
.GetStyle() == wxSTIPPLE
)
1008 gdk_gc_set_ts_origin( m_brushGC
,
1009 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1010 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
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 );
1016 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1020 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1021 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1024 CalcBoundingBox( x
, y
);
1025 CalcBoundingBox( x
+ width
, y
+ height
);
1028 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1030 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1031 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1034 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1035 wxCoord x
, wxCoord y
,
1038 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1040 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1042 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1044 /* scale/translate size and position */
1045 int xx
= XLOG2DEV(x
);
1046 int yy
= YLOG2DEV(y
);
1048 int w
= bitmap
.GetWidth();
1049 int h
= bitmap
.GetHeight();
1051 CalcBoundingBox( x
, y
);
1052 CalcBoundingBox( x
+ w
, y
+ h
);
1054 if (!m_window
) return;
1056 int ww
= XLOG2DEVREL(w
);
1057 int hh
= YLOG2DEVREL(h
);
1059 /* compare to current clipping region */
1060 if (!m_currentClippingRegion
.IsNull())
1062 wxRegion
tmp( xx
,yy
,ww
,hh
);
1063 tmp
.Intersect( m_currentClippingRegion
);
1068 /* scale bitmap if required */
1069 wxBitmap use_bitmap
;
1070 if ((w
!= ww
) || (h
!= hh
))
1072 wxImage image
= bitmap
.ConvertToImage();
1073 image
.Rescale( ww
, hh
);
1075 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1077 use_bitmap
= wxBitmap(image
);
1081 use_bitmap
= bitmap
;
1084 /* apply mask if any */
1085 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1086 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1088 if (useMask
&& mask
)
1090 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1091 #ifndef __WXGTK20__ // TODO fix crash
1092 if (!m_currentClippingRegion
.IsNull())
1095 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1096 GdkGC
*gc
= gdk_gc_new( new_mask
);
1098 gdk_gc_set_foreground( gc
, &col
);
1099 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1101 gdk_gc_set_background( gc
, &col
);
1103 gdk_gc_set_foreground( gc
, &col
);
1104 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1105 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1106 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1107 gdk_gc_set_stipple( gc
, mask
);
1108 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1115 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1117 gdk_gc_set_clip_mask( m_textGC
, mask
);
1118 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1123 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1125 gdk_gc_set_clip_mask( m_penGC
, mask
);
1126 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1130 gdk_bitmap_unref( new_mask
);
1133 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1134 drawing a mono-bitmap (XBitmap) we use the current text GC */
1136 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1138 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1140 /* remove mask again if any */
1141 if (useMask
&& mask
)
1145 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1146 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1147 if (!m_currentClippingRegion
.IsNull())
1148 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1152 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1153 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1154 if (!m_currentClippingRegion
.IsNull())
1155 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1160 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1161 wxCoord width
, wxCoord height
,
1163 wxCoord xsrc
, wxCoord ysrc
,
1166 wxCoord xsrcMask
, wxCoord ysrcMask
)
1168 /* this is the nth try to get this utterly useless function to
1169 work. it now completely ignores the scaling or translation
1170 of the source dc, but scales correctly on the target dc and
1171 knows about possible mask information in a memory dc. */
1173 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1175 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1177 if (!m_window
) return FALSE
;
1180 // transform the source DC coords to the device ones
1181 xsrc
= source
->XLOG2DEV(xsrc
);
1182 ysrc
= source
->YLOG2DEV(ysrc
);
1185 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1186 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1188 bool use_bitmap_method
= FALSE
;
1189 bool is_mono
= FALSE
;
1191 /* TODO: use the mask origin when drawing transparently */
1192 if (xsrcMask
== -1 && ysrcMask
== -1)
1194 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1197 if (srcDC
->m_isMemDC
)
1199 if (!memDC
->m_selected
.Ok()) return FALSE
;
1201 /* we use the "XCopyArea" way to copy a memory dc into
1202 y different window if the memory dc BOTH
1203 a) doesn't have any mask or its mask isn't used
1207 if (useMask
&& (memDC
->m_selected
.GetMask()))
1209 /* we HAVE TO use the direct way for memory dcs
1210 that have mask since the XCopyArea doesn't know
1212 use_bitmap_method
= TRUE
;
1214 else if (memDC
->m_selected
.GetDepth() == 1)
1216 /* we HAVE TO use the direct way for memory dcs
1217 that are bitmaps because XCopyArea doesn't cope
1218 with different bit depths */
1220 use_bitmap_method
= TRUE
;
1222 else if ((xsrc
== 0) && (ysrc
== 0) &&
1223 (width
== memDC
->m_selected
.GetWidth()) &&
1224 (height
== memDC
->m_selected
.GetHeight()))
1226 /* we SHOULD use the direct way if all of the bitmap
1227 in the memory dc is copied in which case XCopyArea
1228 wouldn't be able able to boost performace by reducing
1229 the area to be scaled */
1230 use_bitmap_method
= TRUE
;
1234 use_bitmap_method
= FALSE
;
1238 CalcBoundingBox( xdest
, ydest
);
1239 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1241 /* scale/translate size and position */
1242 wxCoord xx
= XLOG2DEV(xdest
);
1243 wxCoord yy
= YLOG2DEV(ydest
);
1245 wxCoord ww
= XLOG2DEVREL(width
);
1246 wxCoord hh
= YLOG2DEVREL(height
);
1248 /* compare to current clipping region */
1249 if (!m_currentClippingRegion
.IsNull())
1251 wxRegion
tmp( xx
,yy
,ww
,hh
);
1252 tmp
.Intersect( m_currentClippingRegion
);
1257 int old_logical_func
= m_logicalFunction
;
1258 SetLogicalFunction( logical_func
);
1260 if (use_bitmap_method
)
1262 /* scale/translate bitmap size */
1263 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1264 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1266 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1267 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1269 /* scale bitmap if required */
1270 wxBitmap use_bitmap
;
1272 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1274 wxImage image
= memDC
->m_selected
.ConvertToImage();
1275 image
= image
.Scale( bm_ww
, bm_hh
);
1278 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1280 use_bitmap
= wxBitmap(image
);
1284 use_bitmap
= memDC
->m_selected
;
1287 /* apply mask if any */
1288 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1289 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1291 if (useMask
&& mask
)
1293 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1294 #ifndef __WXGTK20__ // TODO fix crash
1295 if (!m_currentClippingRegion
.IsNull())
1298 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1299 GdkGC
*gc
= gdk_gc_new( new_mask
);
1301 gdk_gc_set_foreground( gc
, &col
);
1302 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1304 gdk_gc_set_background( gc
, &col
);
1306 gdk_gc_set_foreground( gc
, &col
);
1307 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1308 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1309 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1310 gdk_gc_set_stipple( gc
, mask
);
1311 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1318 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1320 gdk_gc_set_clip_mask( m_textGC
, mask
);
1321 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1326 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1328 gdk_gc_set_clip_mask( m_penGC
, mask
);
1329 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1332 gdk_bitmap_unref( new_mask
);
1335 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1336 drawing a mono-bitmap (XBitmap) we use the current text GC */
1339 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1341 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1343 /* remove mask again if any */
1344 if (useMask
&& mask
)
1348 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1349 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1350 if (!m_currentClippingRegion
.IsNull())
1351 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1355 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1356 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1357 if (!m_currentClippingRegion
.IsNull())
1358 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1362 else /* use_bitmap_method */
1364 if ((width
!= ww
) || (height
!= hh
))
1366 /* draw source window into a bitmap as we cannot scale
1367 a window in contrast to a bitmap. this would actually
1368 work with memory dcs as well, but we'd lose the mask
1369 information and waste one step in this process since
1370 a memory already has a bitmap. all this is slightly
1371 inefficient as we could take an XImage directly from
1372 an X window, but we'd then also have to care that
1373 the window is not outside the screen (in which case
1374 we'd get a BadMatch or what not).
1375 Is a double XGetImage and combined XGetPixel and
1376 XPutPixel really faster? I'm not sure. look at wxXt
1377 for a different implementation of the same problem. */
1379 wxBitmap
bitmap( width
, height
);
1381 /* copy including child window contents */
1382 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1383 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1385 xsrc
, ysrc
, width
, height
);
1386 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1389 wxImage image
= bitmap
.ConvertToImage();
1390 image
= image
.Scale( ww
, hh
);
1392 /* convert to bitmap */
1393 bitmap
= wxBitmap(image
);
1395 /* draw scaled bitmap */
1396 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1401 /* No scaling and not a memory dc with a mask either */
1403 /* copy including child window contents */
1404 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1405 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1407 xsrc
, ysrc
, width
, height
);
1408 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1412 SetLogicalFunction( old_logical_func
);
1416 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1418 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1420 if (!m_window
) return;
1422 if (text
.empty()) return;
1425 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1427 wxCHECK_RET( font
, wxT("invalid font") );
1435 wxCHECK_RET( m_context
, wxT("no Pango context") );
1436 wxCHECK_RET( m_layout
, wxT("o Pango layout") );
1437 wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") );
1440 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
1441 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1443 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( text
);
1444 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1445 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1448 if (m_scaleY
!= 1.0)
1450 // If there is a user or actually any scale applied to
1451 // the device context, scale the font.
1453 // scale font description
1454 gint oldSize
= pango_font_description_get_size( m_fontdesc
);
1455 double size
= oldSize
;
1456 size
= size
* m_scaleY
;
1457 pango_font_description_set_size( m_fontdesc
, (gint
)size
);
1459 // actually apply scaled font
1460 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1463 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1465 // reset unscaled size
1466 pango_font_description_set_size( m_fontdesc
, oldSize
);
1468 // actually apply scaled font
1469 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1474 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1479 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1484 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1485 wxCoord height
= font
->ascent
+ font
->descent
;
1487 if ( m_backgroundMode
== wxSOLID
)
1489 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1490 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1491 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1493 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1495 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1496 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1497 properties (see wxXt implementation) */
1498 if (m_font
.GetUnderlined())
1500 wxCoord ul_y
= y
+ font
->ascent
;
1501 if (font
->descent
> 0) ul_y
++;
1502 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1504 #endif // GTK+ 2.0/1.x
1506 width
= wxCoord(width
/ m_scaleX
);
1507 height
= wxCoord(height
/ m_scaleY
);
1508 CalcBoundingBox (x
+ width
, y
+ height
);
1509 CalcBoundingBox (x
, y
);
1512 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1516 DrawText(text
, x
, y
);
1520 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1522 if (!m_window
) return;
1525 // implement later without GdkFont for GTK 2.0
1528 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1530 wxCHECK_RET( font
, wxT("invalid font") );
1532 // the size of the text
1533 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1534 wxCoord h
= font
->ascent
+ font
->descent
;
1536 // draw the string normally
1539 dc
.SelectObject(src
);
1540 dc
.SetFont(GetFont());
1541 dc
.SetBackground(*wxWHITE_BRUSH
);
1542 dc
.SetBrush(*wxBLACK_BRUSH
);
1544 dc
.DrawText(text
, 0, 0);
1545 dc
.SelectObject(wxNullBitmap
);
1547 // Calculate the size of the rotated bounding box.
1548 double rad
= DegToRad(angle
);
1549 double dx
= cos(rad
),
1552 // the rectngle vertices are counted clockwise with the first one being at
1553 // (0, 0) (or, rather, at (x, y))
1555 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1558 double x3
= x4
+ x2
,
1562 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1563 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1564 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1565 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1567 // prepare to blit-with-rotate the bitmap to the DC
1568 wxImage image
= src
.ConvertToImage();
1570 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1571 *colBack
= m_textBackgroundColour
.GetColor();
1573 bool textColSet
= TRUE
;
1575 unsigned char *data
= image
.GetData();
1577 // paint pixel by pixel
1578 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1580 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1582 // transform source coords to dest coords
1583 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1584 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1585 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1586 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1589 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1590 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1592 // change colour if needed
1593 if ( textPixel
!= textColSet
)
1595 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1598 textColSet
= textPixel
;
1601 // don't use DrawPoint() because it uses the current pen
1602 // colour, and we don't need it here
1603 gdk_draw_point( m_window
, m_textGC
,
1604 XLOG2DEV(x
) + dstX
, YLOG2DEV(y
) + dstY
);
1609 // it would be better to draw with non underlined font and draw the line
1610 // manually here (it would be more straight...)
1612 if ( m_font
.GetUnderlined() )
1614 gdk_draw_line( m_window
, m_textGC
,
1615 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1616 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1620 // restore the font colour
1621 gdk_gc_set_foreground( m_textGC
, colText
);
1623 // update the bounding box
1624 CalcBoundingBox(x
+ minX
, y
+ minY
);
1625 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1629 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1630 wxCoord
*width
, wxCoord
*height
,
1631 wxCoord
*descent
, wxCoord
*externalLeading
,
1632 wxFont
*theFont
) const
1634 if (string
.IsEmpty())
1636 if (width
) (*width
) = 0;
1637 if (height
) (*height
) = 0;
1642 // Set new font description
1644 pango_layout_set_font_description( m_layout
, theFont
->GetNativeFontInfo()->description
);
1646 // Set layout's text
1648 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
1649 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1651 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( string
);
1652 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1653 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1657 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1659 if (width
) (*width
) = (wxCoord
) w
;
1660 if (height
) (*height
) = (wxCoord
) h
;
1663 // Do something about metrics here. TODO.
1666 if (externalLeading
) (*externalLeading
) = 0; // ??
1668 // Reset old font description
1670 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1672 wxFont fontToUse
= m_font
;
1673 if (theFont
) fontToUse
= *theFont
;
1675 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1676 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1677 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1678 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1679 if (externalLeading
) (*externalLeading
) = 0; // ??
1683 wxCoord
wxWindowDC::GetCharWidth() const
1686 pango_layout_set_text( m_layout
, "H", 1 );
1688 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1691 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1692 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1694 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1698 wxCoord
wxWindowDC::GetCharHeight() const
1701 pango_layout_set_text( m_layout
, "H", 1 );
1703 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1706 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1707 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1709 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1713 void wxWindowDC::Clear()
1715 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1717 if (!m_window
) return;
1719 // VZ: the code below results in infinite recursion and crashes when
1720 // dc.Clear() is done from OnPaint() so I disable it for now.
1721 // I don't know what the correct fix is but Clear() surely should not
1722 // reenter OnPaint()!
1724 /* - we either are a memory dc or have a window as the
1725 owner. anything else shouldn't happen.
1726 - we don't use gdk_window_clear() as we don't set
1727 the window's background colour anymore. it is too
1728 much pain to keep the DC's and the window's back-
1729 ground colour in synch. */
1740 GetSize( &width
, &height
);
1741 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1746 GetSize( &width
, &height
);
1747 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1751 void wxWindowDC::SetFont( const wxFont
&font
)
1759 pango_font_description_free( m_fontdesc
);
1761 m_fontdesc
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description
);
1766 PangoContext
*oldContext
= m_context
;
1768 // We might want to use the X11 context for faster
1769 // rendering on screen
1770 if (m_font
.GetNoAntiAliasing())
1771 m_context
= m_owner
->GtkGetPangoX11Context();
1773 m_context
= m_owner
->GtkGetPangoDefaultContext();
1775 // If we switch back/forth between different contexts
1776 // we also have to create a new layout. I think so,
1777 // at least, and it doesn't hurt to do it.
1778 if (oldContext
!= m_context
)
1781 g_object_unref( G_OBJECT( m_layout
) );
1783 m_layout
= pango_layout_new( m_context
);
1787 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1792 void wxWindowDC::SetPen( const wxPen
&pen
)
1794 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1796 if (m_pen
== pen
) return;
1800 if (!m_pen
.Ok()) return;
1802 if (!m_window
) return;
1804 gint width
= m_pen
.GetWidth();
1807 // CMB: if width is non-zero scale it with the dc
1812 // X doesn't allow different width in x and y and so we take
1815 ( fabs((double) XLOG2DEVREL(width
)) +
1816 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1820 static const wxGTKDash dotted
[] = {1, 1};
1821 static const wxGTKDash short_dashed
[] = {2, 2};
1822 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1823 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1825 // We express dash pattern in pen width unit, so we are
1826 // independent of zoom factor and so on...
1828 const wxGTKDash
*req_dash
;
1830 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1831 switch (m_pen
.GetStyle())
1835 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1836 req_nb_dash
= m_pen
.GetDashCount();
1837 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1842 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1849 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1851 req_dash
= wxCoord_dashed
;
1856 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1858 req_dash
= short_dashed
;
1863 // lineStyle = GDK_LINE_DOUBLE_DASH;
1864 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1866 req_dash
= dotted_dashed
;
1871 case wxSTIPPLE_MASK_OPAQUE
:
1876 lineStyle
= GDK_LINE_SOLID
;
1877 req_dash
= (wxGTKDash
*)NULL
;
1883 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1884 if (req_dash
&& req_nb_dash
)
1886 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1889 for (int i
= 0; i
< req_nb_dash
; i
++)
1890 real_req_dash
[i
] = req_dash
[i
] * width
;
1891 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1892 delete[] real_req_dash
;
1896 // No Memory. We use non-scaled dash pattern...
1897 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1900 #endif // GTK+ > 1.0
1902 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1903 switch (m_pen
.GetCap())
1905 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1906 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1913 capStyle
= GDK_CAP_NOT_LAST
;
1917 capStyle
= GDK_CAP_ROUND
;
1923 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1924 switch (m_pen
.GetJoin())
1926 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1927 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1929 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1932 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1934 m_pen
.GetColour().CalcPixel( m_cmap
);
1935 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1938 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1940 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1942 if (m_brush
== brush
) return;
1946 if (!m_brush
.Ok()) return;
1948 if (!m_window
) return;
1950 m_brush
.GetColour().CalcPixel( m_cmap
);
1951 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1953 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1955 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1957 if (m_brush
.GetStipple()->GetPixmap())
1959 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1960 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1964 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1965 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1969 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1971 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1972 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1975 if (IS_HATCH(m_brush
.GetStyle()))
1977 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1978 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1979 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1983 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1985 /* CMB 21/7/98: Added SetBackground. Sets background brush
1986 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1988 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1990 if (m_backgroundBrush
== brush
) return;
1992 m_backgroundBrush
= brush
;
1994 if (!m_backgroundBrush
.Ok()) return;
1996 if (!m_window
) return;
1998 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1999 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
2000 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
2001 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2002 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2004 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
2006 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
2008 if (m_backgroundBrush
.GetStipple()->GetPixmap())
2010 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
2011 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
2015 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2016 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
2020 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
2022 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2023 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
2024 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
2028 void wxWindowDC::SetLogicalFunction( int function
)
2030 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2032 if (m_logicalFunction
== function
)
2035 // VZ: shouldn't this be a CHECK?
2042 case wxXOR
: mode
= GDK_XOR
; break;
2043 case wxINVERT
: mode
= GDK_INVERT
; break;
2044 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
2045 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
2046 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
2047 case wxCLEAR
: mode
= GDK_CLEAR
; break;
2048 case wxSET
: mode
= GDK_SET
; break;
2049 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
2050 case wxAND
: mode
= GDK_AND
; break;
2051 case wxOR
: mode
= GDK_OR
; break;
2052 case wxEQUIV
: mode
= GDK_EQUIV
; break;
2053 case wxNAND
: mode
= GDK_NAND
; break;
2054 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
2055 case wxCOPY
: mode
= GDK_COPY
; break;
2056 case wxNO_OP
: mode
= GDK_NOOP
; break;
2057 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
2059 // unsupported by GTK
2060 case wxNOR
: mode
= GDK_COPY
; break;
2061 #endif // GTK+ > 1.0
2063 wxFAIL_MSG( wxT("unsupported logical function") );
2067 m_logicalFunction
= function
;
2069 gdk_gc_set_function( m_penGC
, mode
);
2070 gdk_gc_set_function( m_brushGC
, mode
);
2072 // to stay compatible with wxMSW, we don't apply ROPs to the text
2073 // operations (i.e. DrawText/DrawRotatedText).
2074 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2075 gdk_gc_set_function( m_textGC
, mode
);
2078 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2080 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2082 // don't set m_textForegroundColour to an invalid colour as we'd crash
2083 // later then (we use m_textForegroundColour.GetColor() without checking
2085 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
2088 m_textForegroundColour
= col
;
2092 m_textForegroundColour
.CalcPixel( m_cmap
);
2093 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
2097 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2099 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2102 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
2105 m_textBackgroundColour
= col
;
2109 m_textBackgroundColour
.CalcPixel( m_cmap
);
2110 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
2114 void wxWindowDC::SetBackgroundMode( int mode
)
2116 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2118 m_backgroundMode
= mode
;
2120 if (!m_window
) return;
2122 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2123 // transparent/solid background mode
2125 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2127 gdk_gc_set_fill( m_brushGC
,
2128 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2132 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2134 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2137 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2139 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2141 if (!m_window
) return;
2144 rect
.x
= XLOG2DEV(x
);
2145 rect
.y
= YLOG2DEV(y
);
2146 rect
.width
= XLOG2DEVREL(width
);
2147 rect
.height
= YLOG2DEVREL(height
);
2149 if (!m_currentClippingRegion
.IsNull())
2150 m_currentClippingRegion
.Intersect( rect
);
2152 m_currentClippingRegion
.Union( rect
);
2154 #if USE_PAINT_REGION
2155 if (!m_paintClippingRegion
.IsNull())
2156 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2159 wxCoord xx
, yy
, ww
, hh
;
2160 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2161 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2163 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2164 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2165 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2166 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2169 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2171 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2175 DestroyClippingRegion();
2179 if (!m_window
) return;
2181 if (!m_currentClippingRegion
.IsNull())
2182 m_currentClippingRegion
.Intersect( region
);
2184 m_currentClippingRegion
.Union( region
);
2186 #if USE_PAINT_REGION
2187 if (!m_paintClippingRegion
.IsNull())
2188 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2191 wxCoord xx
, yy
, ww
, hh
;
2192 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2193 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2195 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2196 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2197 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2198 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2201 void wxWindowDC::DestroyClippingRegion()
2203 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2205 wxDC::DestroyClippingRegion();
2207 m_currentClippingRegion
.Clear();
2209 #if USE_PAINT_REGION
2210 if (!m_paintClippingRegion
.IsEmpty())
2211 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2214 if (!m_window
) return;
2216 if (m_currentClippingRegion
.IsEmpty())
2218 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2219 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2220 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2221 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2225 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2226 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2227 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2228 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2232 void wxWindowDC::Destroy()
2234 if (m_penGC
) wxFreePoolGC( m_penGC
);
2235 m_penGC
= (GdkGC
*) NULL
;
2236 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2237 m_brushGC
= (GdkGC
*) NULL
;
2238 if (m_textGC
) wxFreePoolGC( m_textGC
);
2239 m_textGC
= (GdkGC
*) NULL
;
2240 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2241 m_bgGC
= (GdkGC
*) NULL
;
2244 void wxWindowDC::ComputeScaleAndOrigin()
2246 /* CMB: copy scale to see if it changes */
2247 double origScaleX
= m_scaleX
;
2248 double origScaleY
= m_scaleY
;
2250 wxDC::ComputeScaleAndOrigin();
2252 /* CMB: if scale has changed call SetPen to recalulate the line width */
2253 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2256 /* this is a bit artificial, but we need to force wxDC to think
2257 the pen has changed */
2264 // Resolution in pixels per logical inch
2265 wxSize
wxWindowDC::GetPPI() const
2267 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2270 int wxWindowDC::GetDepth() const
2272 wxFAIL_MSG(wxT("not implemented"));
2278 //-----------------------------------------------------------------------------
2280 //-----------------------------------------------------------------------------
2282 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2284 wxPaintDC::wxPaintDC( wxWindow
*win
)
2287 #if USE_PAINT_REGION
2288 if (!win
->m_clipPaintRegion
)
2291 m_paintClippingRegion
= win
->GetUpdateRegion();
2292 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2295 m_paintClippingRegion
= win
->GetUpdateRegion();
2296 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2299 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2301 gdk_gc_set_clip_region( m_penGC
, region
);
2302 gdk_gc_set_clip_region( m_brushGC
, region
);
2303 gdk_gc_set_clip_region( m_textGC
, region
);
2304 gdk_gc_set_clip_region( m_bgGC
, region
);
2307 #endif // USE_PAINT_REGION
2310 //-----------------------------------------------------------------------------
2312 //-----------------------------------------------------------------------------
2314 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2316 wxClientDC::wxClientDC( wxWindow
*win
)
2319 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2321 #ifdef __WXUNIVERSAL__
2322 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2323 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2324 wxSize size
= win
->GetClientSize();
2325 SetClippingRegion(wxPoint(0, 0), size
);
2326 #endif // __WXUNIVERSAL__
2329 void wxClientDC::DoGetSize(int *width
, int *height
) const
2331 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2333 m_owner
->GetClientSize( width
, height
);
2336 // ----------------------------------------------------------------------------
2338 // ----------------------------------------------------------------------------
2340 class wxDCModule
: public wxModule
2347 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2350 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2352 bool wxDCModule::OnInit()
2358 void wxDCModule::OnExit()