]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/dcclient.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
11 #pragma implementation "dcclient.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
18 #define XCopyPlane XCOPYPLANE
21 #include "wx/dcclient.h"
22 #include "wx/dcmemory.h"
24 #include "wx/module.h"
26 #include "wx/fontutil.h"
28 #include "wx/gtk/win_gtk.h"
30 #include <math.h> // for floating-point functions
34 #include <gdk/gdkprivate.h>
37 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
41 #define USE_PAINT_REGION 1
43 //-----------------------------------------------------------------------------
45 //-----------------------------------------------------------------------------
55 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
56 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
59 static GdkPixmap
*hatches
[num_hatches
];
60 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
62 extern GtkWidget
*wxGetRootWindow();
64 //-----------------------------------------------------------------------------
66 //-----------------------------------------------------------------------------
68 const double RAD2DEG
= 180.0 / M_PI
;
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
75 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
77 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
79 //-----------------------------------------------------------------------------
80 // temporary implementation of the missing GDK function
81 //-----------------------------------------------------------------------------
83 #include "gdk/gdkprivate.h"
85 void gdk_wx_draw_bitmap(GdkDrawable
*drawable
,
95 gint src_width
, src_height
;
97 GdkWindowPrivate
*drawable_private
;
98 GdkWindowPrivate
*src_private
;
99 GdkGCPrivate
*gc_private
;
102 g_return_if_fail (drawable
!= NULL
);
103 g_return_if_fail (src
!= NULL
);
104 g_return_if_fail (gc
!= NULL
);
107 // This doesn't seem to exist for bitmaps (1-bit)
108 // if (GDK_WINDOW_DESTROYED(drawable) || GDK_WINDOW_DESTROYED(src))
111 gdk_drawable_get_size(src
, &src_width
, &src_height
);
113 drawable_private
= (GdkWindowPrivate
*) drawable
;
114 src_private
= (GdkWindowPrivate
*) src
;
115 if (drawable_private
->destroyed
|| src_private
->destroyed
)
118 src_width
= src_private
->width
;
119 src_height
= src_private
->height
;
121 gc_private
= (GdkGCPrivate
*) gc
;
124 if (width
== -1) width
= src_width
;
125 if (height
== -1) height
= src_height
;
128 XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
),
130 GDK_WINDOW_XID(drawable
),
137 XCopyPlane( drawable_private
->xdisplay
,
138 src_private
->xwindow
,
139 drawable_private
->xwindow
,
148 //-----------------------------------------------------------------------------
149 // Implement Pool of Graphic contexts. Creating them takes too much time.
150 //-----------------------------------------------------------------------------
152 #define GC_POOL_SIZE 200
178 #define GC_POOL_ALLOC_SIZE 100
180 static int wxGCPoolSize
= 0;
182 static wxGC
*wxGCPool
= NULL
;
184 static void wxInitGCPool()
186 // This really could wait until the first call to
187 // wxGetPoolGC, but we will make the first allocation
188 // now when other initialization is being performed.
190 // Set initial pool size.
191 wxGCPoolSize
= GC_POOL_ALLOC_SIZE
;
193 // Allocate initial pool.
194 wxGCPool
= (wxGC
*)malloc(wxGCPoolSize
* sizeof(wxGC
));
195 if (wxGCPool
== NULL
)
197 // If we cannot malloc, then fail with error
198 // when debug is enabled. If debug is not enabled,
199 // the problem will eventually get caught
201 wxFAIL_MSG( wxT("Cannot allocate GC pool") );
205 // Zero initial pool.
206 memset(wxGCPool
, 0, wxGCPoolSize
* sizeof(wxGC
));
209 static void wxCleanUpGCPool()
211 for (int i
= 0; i
< wxGCPoolSize
; i
++)
213 if (wxGCPool
[i
].m_gc
)
214 gdk_gc_unref( wxGCPool
[i
].m_gc
);
222 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
226 // Look for an available GC.
227 for (int i
= 0; i
< wxGCPoolSize
; i
++)
229 if (!wxGCPool
[i
].m_gc
)
231 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
232 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
233 wxGCPool
[i
].m_type
= type
;
234 wxGCPool
[i
].m_used
= FALSE
;
236 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
238 wxGCPool
[i
].m_used
= TRUE
;
239 return wxGCPool
[i
].m_gc
;
243 // We did not find an available GC.
244 // We need to grow the GC pool.
245 pptr
= (wxGC
*)realloc(wxGCPool
,
246 (wxGCPoolSize
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
));
249 // Initialize newly allocated pool.
251 memset(&wxGCPool
[wxGCPoolSize
], 0,
252 GC_POOL_ALLOC_SIZE
*sizeof(wxGC
));
254 // Initialize entry we will return.
255 wxGCPool
[wxGCPoolSize
].m_gc
= gdk_gc_new( window
);
256 gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE
);
257 wxGCPool
[wxGCPoolSize
].m_type
= type
;
258 wxGCPool
[wxGCPoolSize
].m_used
= TRUE
;
260 // Set new value of pool size.
261 wxGCPoolSize
+= GC_POOL_ALLOC_SIZE
;
263 // Return newly allocated entry.
264 return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
;
267 // The realloc failed. Fall through to error.
268 wxFAIL_MSG( wxT("No GC available") );
270 return (GdkGC
*) NULL
;
273 static void wxFreePoolGC( GdkGC
*gc
)
275 for (int i
= 0; i
< wxGCPoolSize
; i
++)
277 if (wxGCPool
[i
].m_gc
== gc
)
279 wxGCPool
[i
].m_used
= FALSE
;
284 wxFAIL_MSG( wxT("Wrong GC") );
287 //-----------------------------------------------------------------------------
289 //-----------------------------------------------------------------------------
291 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
293 wxWindowDC::wxWindowDC()
295 m_penGC
= (GdkGC
*) NULL
;
296 m_brushGC
= (GdkGC
*) NULL
;
297 m_textGC
= (GdkGC
*) NULL
;
298 m_bgGC
= (GdkGC
*) NULL
;
299 m_cmap
= (GdkColormap
*) NULL
;
301 m_isScreenDC
= FALSE
;
302 m_owner
= (wxWindow
*)NULL
;
304 m_context
= (PangoContext
*)NULL
;
305 m_layout
= (PangoLayout
*)NULL
;
306 m_fontdesc
= (PangoFontDescription
*)NULL
;
310 wxWindowDC::wxWindowDC( wxWindow
*window
)
312 wxASSERT_MSG( window
, wxT("DC needs a window") );
314 m_penGC
= (GdkGC
*) NULL
;
315 m_brushGC
= (GdkGC
*) NULL
;
316 m_textGC
= (GdkGC
*) NULL
;
317 m_bgGC
= (GdkGC
*) NULL
;
318 m_cmap
= (GdkColormap
*) NULL
;
319 m_owner
= (wxWindow
*)NULL
;
321 m_isScreenDC
= FALSE
;
322 m_font
= window
->GetFont();
324 GtkWidget
*widget
= window
->m_wxwindow
;
326 // Some controls don't have m_wxwindow - like wxStaticBox, but the user
327 // code should still be able to create wxClientDCs for them, so we will
328 // use the parent window here then.
331 window
= window
->GetParent();
332 widget
= window
->m_wxwindow
;
335 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
338 m_context
= window
->GtkGetPangoDefaultContext();
339 m_layout
= pango_layout_new( m_context
);
340 m_fontdesc
= pango_font_description_copy( widget
->style
->font_desc
);
343 GtkPizza
*pizza
= GTK_PIZZA( widget
);
344 m_window
= pizza
->bin_window
;
346 // Window not realized ?
349 // Don't report problems as per MSW.
355 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
359 /* this must be done after SetUpDC, bacause SetUpDC calls the
360 repective SetBrush, SetPen, SetBackground etc functions
361 to set up the DC. SetBackground call m_owner->SetBackground
362 and this might not be desired as the standard dc background
363 is white whereas a window might assume gray to be the
364 standard (as e.g. wxStatusBar) */
369 wxWindowDC::~wxWindowDC()
375 g_object_unref( G_OBJECT( m_layout
) );
377 pango_font_description_free( m_fontdesc
);
381 void wxWindowDC::SetUpDC()
385 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
389 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
390 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
391 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
392 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
395 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
397 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
398 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
399 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
400 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
404 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
405 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
406 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
407 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
410 /* background colour */
411 m_backgroundBrush
= *wxWHITE_BRUSH
;
412 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
413 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
416 m_textForegroundColour
.CalcPixel( m_cmap
);
417 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
419 m_textBackgroundColour
.CalcPixel( m_cmap
);
420 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
422 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
425 m_pen
.GetColour().CalcPixel( m_cmap
);
426 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
427 gdk_gc_set_background( m_penGC
, bg_col
);
429 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
432 m_brush
.GetColour().CalcPixel( m_cmap
);
433 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
434 gdk_gc_set_background( m_brushGC
, bg_col
);
436 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
439 gdk_gc_set_background( m_bgGC
, bg_col
);
440 gdk_gc_set_foreground( m_bgGC
, bg_col
);
442 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
445 gdk_gc_set_function( m_textGC
, GDK_COPY
);
446 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
447 gdk_gc_set_function( m_penGC
, GDK_COPY
);
450 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
451 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
452 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
453 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
457 hatch_bitmap
= hatches
;
458 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
459 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
460 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
461 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
462 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
463 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
467 void wxWindowDC::DoGetSize( int* width
, int* height
) const
469 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
471 m_owner
->GetSize(width
, height
);
474 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
475 const wxColour
& col
, int style
);
477 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
478 const wxColour
& col
, int style
)
480 return wxDoFloodFill(this, x
, y
, col
, style
);
483 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
485 // Generic (and therefore rather inefficient) method.
486 // Could be improved.
488 wxBitmap
bitmap(1, 1);
489 memdc
.SelectObject(bitmap
);
490 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
491 memdc
.SelectObject(wxNullBitmap
);
493 wxImage image
= bitmap
.ConvertToImage();
494 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
498 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
500 wxCHECK_RET( Ok(), wxT("invalid window dc") );
502 if (m_pen
.GetStyle() != wxTRANSPARENT
)
505 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
507 CalcBoundingBox(x1
, y1
);
508 CalcBoundingBox(x2
, y2
);
512 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
514 wxCHECK_RET( Ok(), wxT("invalid window dc") );
516 if (m_pen
.GetStyle() != wxTRANSPARENT
)
521 wxCoord xx
= XLOG2DEV(x
);
522 wxCoord yy
= YLOG2DEV(y
);
525 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
526 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
531 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
532 wxCoord xc
, wxCoord yc
)
534 wxCHECK_RET( Ok(), wxT("invalid window dc") );
536 wxCoord xx1
= XLOG2DEV(x1
);
537 wxCoord yy1
= YLOG2DEV(y1
);
538 wxCoord xx2
= XLOG2DEV(x2
);
539 wxCoord yy2
= YLOG2DEV(y2
);
540 wxCoord xxc
= XLOG2DEV(xc
);
541 wxCoord yyc
= YLOG2DEV(yc
);
542 double dx
= xx1
- xxc
;
543 double dy
= yy1
- yyc
;
544 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
545 wxCoord r
= (wxCoord
)radius
;
546 double radius1
, radius2
;
548 if (xx1
== xx2
&& yy1
== yy2
)
556 radius1
= radius2
= 0.0;
560 radius1
= (xx1
- xxc
== 0) ?
561 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
562 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
563 radius2
= (xx2
- xxc
== 0) ?
564 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
565 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
567 wxCoord alpha1
= wxCoord(radius1
* 64.0);
568 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
569 while (alpha2
<= 0) alpha2
+= 360*64;
570 while (alpha1
> 360*64) alpha1
-= 360*64;
574 if (m_brush
.GetStyle() != wxTRANSPARENT
)
576 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
578 gdk_gc_set_ts_origin( m_textGC
,
579 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
580 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
581 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
582 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
584 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
586 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
587 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
588 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
590 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
592 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
593 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
594 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
596 if (m_brush
.GetStyle() == wxSTIPPLE
)
598 gdk_gc_set_ts_origin( m_brushGC
,
599 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
600 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
601 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
602 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
606 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
610 if (m_pen
.GetStyle() != wxTRANSPARENT
)
612 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
614 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
615 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
619 CalcBoundingBox (x1
, y1
);
620 CalcBoundingBox (x2
, y2
);
623 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
625 wxCHECK_RET( Ok(), wxT("invalid window dc") );
627 wxCoord xx
= XLOG2DEV(x
);
628 wxCoord yy
= YLOG2DEV(y
);
629 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
630 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
632 // CMB: handle -ve width and/or height
633 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
634 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
638 wxCoord start
= wxCoord(sa
* 64.0);
639 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
641 if (m_brush
.GetStyle() != wxTRANSPARENT
)
643 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
645 gdk_gc_set_ts_origin( m_textGC
,
646 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
647 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
648 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
649 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
651 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
653 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
654 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
655 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
657 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
659 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
660 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
661 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
663 if (m_brush
.GetStyle() == wxSTIPPLE
)
665 gdk_gc_set_ts_origin( m_brushGC
,
666 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
667 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
668 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
669 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
673 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
677 if (m_pen
.GetStyle() != wxTRANSPARENT
)
678 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
681 CalcBoundingBox (x
, y
);
682 CalcBoundingBox (x
+ width
, y
+ height
);
685 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
687 wxCHECK_RET( Ok(), wxT("invalid window dc") );
689 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
690 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
692 CalcBoundingBox (x
, y
);
695 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
697 wxCHECK_RET( Ok(), wxT("invalid window dc") );
699 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
702 GdkPoint
*gpts
= new GdkPoint
[n
];
705 wxFAIL_MSG( wxT("Cannot allocate PolyLine") );
709 for (int i
= 0; i
< n
; i
++)
711 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
712 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
);
714 CalcBoundingBox( x1
+ xoffset
, y1
+ yoffset
);
721 gdk_draw_lines( m_window
, m_penGC
, gpts
, n
);
726 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
728 wxCHECK_RET( Ok(), wxT("invalid window dc") );
732 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
734 for (i
= 0 ; i
< n
; i
++)
736 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
737 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
739 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
744 if (m_brush
.GetStyle() != wxTRANSPARENT
)
746 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
748 gdk_gc_set_ts_origin( m_textGC
,
749 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
750 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
751 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
752 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
754 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
756 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
757 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
758 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
760 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
762 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
763 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
764 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
766 if (m_brush
.GetStyle() == wxSTIPPLE
)
768 gdk_gc_set_ts_origin( m_brushGC
,
769 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
770 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
771 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
772 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
776 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
780 if (m_pen
.GetStyle() != wxTRANSPARENT
)
782 for (i
= 0 ; i
< n
; i
++)
784 gdk_draw_line( m_window
, m_penGC
,
787 gdkpoints
[(i
+1)%n
].x
,
788 gdkpoints
[(i
+1)%n
].y
);
796 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
798 wxCHECK_RET( Ok(), wxT("invalid window dc") );
800 wxCoord xx
= XLOG2DEV(x
);
801 wxCoord yy
= YLOG2DEV(y
);
802 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
803 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
805 // CMB: draw nothing if transformed w or h is 0
806 if (ww
== 0 || hh
== 0) return;
808 // CMB: handle -ve width and/or height
809 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
810 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
814 if (m_brush
.GetStyle() != wxTRANSPARENT
)
816 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
818 gdk_gc_set_ts_origin( m_textGC
,
819 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
820 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
821 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
822 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
824 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
826 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
827 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
828 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
830 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
832 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
833 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
834 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
836 if (m_brush
.GetStyle() == wxSTIPPLE
)
838 gdk_gc_set_ts_origin( m_brushGC
,
839 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
840 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
841 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
842 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
846 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
850 if (m_pen
.GetStyle() != wxTRANSPARENT
)
851 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
854 CalcBoundingBox( x
, y
);
855 CalcBoundingBox( x
+ width
, y
+ height
);
858 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
860 wxCHECK_RET( Ok(), wxT("invalid window dc") );
862 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
864 wxCoord xx
= XLOG2DEV(x
);
865 wxCoord yy
= YLOG2DEV(y
);
866 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
867 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
868 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
870 // CMB: handle -ve width and/or height
871 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
872 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
874 // CMB: if radius is zero use DrawRectangle() instead to avoid
875 // X drawing errors with small radii
878 DrawRectangle( x
, y
, width
, height
);
882 // CMB: draw nothing if transformed w or h is 0
883 if (ww
== 0 || hh
== 0) return;
885 // CMB: adjust size if outline is drawn otherwise the result is
886 // 1 pixel too wide and high
887 if (m_pen
.GetStyle() != wxTRANSPARENT
)
895 // CMB: ensure dd is not larger than rectangle otherwise we
896 // get an hour glass shape
898 if (dd
> ww
) dd
= ww
;
899 if (dd
> hh
) dd
= hh
;
902 if (m_brush
.GetStyle() != wxTRANSPARENT
)
904 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
906 gdk_gc_set_ts_origin( m_textGC
,
907 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
908 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
909 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
910 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
911 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
912 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
913 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
914 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
915 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
917 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
919 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
920 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
921 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
922 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
923 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
924 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
925 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
926 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
928 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
930 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
931 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
932 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
933 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
934 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
935 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
936 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
937 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
939 if (m_brush
.GetStyle() == wxSTIPPLE
)
941 gdk_gc_set_ts_origin( m_brushGC
,
942 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
943 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
944 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
945 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
946 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
947 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
948 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
949 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
950 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
954 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
955 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
956 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
957 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
958 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
959 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
963 if (m_pen
.GetStyle() != wxTRANSPARENT
)
965 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
966 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
967 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
968 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
969 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
970 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
971 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
972 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
976 // this ignores the radius
977 CalcBoundingBox( x
, y
);
978 CalcBoundingBox( x
+ width
, y
+ height
);
981 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
983 wxCHECK_RET( Ok(), wxT("invalid window dc") );
985 wxCoord xx
= XLOG2DEV(x
);
986 wxCoord yy
= YLOG2DEV(y
);
987 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
988 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
990 // CMB: handle -ve width and/or height
991 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
992 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
996 if (m_brush
.GetStyle() != wxTRANSPARENT
)
998 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1000 gdk_gc_set_ts_origin( m_textGC
,
1001 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1002 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1003 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1004 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
1006 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
1008 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
1009 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1010 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1012 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
1014 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
1015 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1016 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1018 if (m_brush
.GetStyle() == wxSTIPPLE
)
1020 gdk_gc_set_ts_origin( m_brushGC
,
1021 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
1022 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
1023 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1024 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
1028 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1032 if (m_pen
.GetStyle() != wxTRANSPARENT
)
1033 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
1036 CalcBoundingBox( x
, y
);
1037 CalcBoundingBox( x
+ width
, y
+ height
);
1040 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
1042 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
1043 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
1046 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
1047 wxCoord x
, wxCoord y
,
1050 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1052 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1054 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1056 /* scale/translate size and position */
1057 int xx
= XLOG2DEV(x
);
1058 int yy
= YLOG2DEV(y
);
1060 int w
= bitmap
.GetWidth();
1061 int h
= bitmap
.GetHeight();
1063 CalcBoundingBox( x
, y
);
1064 CalcBoundingBox( x
+ w
, y
+ h
);
1066 if (!m_window
) return;
1068 int ww
= XLOG2DEVREL(w
);
1069 int hh
= YLOG2DEVREL(h
);
1071 /* compare to current clipping region */
1072 if (!m_currentClippingRegion
.IsNull())
1074 wxRegion
tmp( xx
,yy
,ww
,hh
);
1075 tmp
.Intersect( m_currentClippingRegion
);
1080 /* scale bitmap if required */
1081 wxBitmap use_bitmap
;
1082 if ((w
!= ww
) || (h
!= hh
))
1084 wxImage image
= bitmap
.ConvertToImage();
1085 image
.Rescale( ww
, hh
);
1087 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1089 use_bitmap
= wxBitmap(image
);
1093 use_bitmap
= bitmap
;
1096 /* apply mask if any */
1097 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1098 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1100 if (useMask
&& mask
)
1102 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1103 #ifndef __WXGTK20__ // TODO fix crash
1104 if (!m_currentClippingRegion
.IsNull())
1107 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1108 GdkGC
*gc
= gdk_gc_new( new_mask
);
1110 gdk_gc_set_foreground( gc
, &col
);
1111 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1113 gdk_gc_set_background( gc
, &col
);
1115 gdk_gc_set_foreground( gc
, &col
);
1116 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1117 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1118 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1119 gdk_gc_set_stipple( gc
, mask
);
1120 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1127 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1129 gdk_gc_set_clip_mask( m_textGC
, mask
);
1130 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1135 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1137 gdk_gc_set_clip_mask( m_penGC
, mask
);
1138 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1142 gdk_bitmap_unref( new_mask
);
1145 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1146 drawing a mono-bitmap (XBitmap) we use the current text GC */
1148 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1150 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1152 /* remove mask again if any */
1153 if (useMask
&& mask
)
1157 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1158 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1159 if (!m_currentClippingRegion
.IsNull())
1160 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1164 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1165 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1166 if (!m_currentClippingRegion
.IsNull())
1167 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1172 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1173 wxCoord width
, wxCoord height
,
1175 wxCoord xsrc
, wxCoord ysrc
,
1178 wxCoord xsrcMask
, wxCoord ysrcMask
)
1180 /* this is the nth try to get this utterly useless function to
1181 work. it now completely ignores the scaling or translation
1182 of the source dc, but scales correctly on the target dc and
1183 knows about possible mask information in a memory dc. */
1185 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1187 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1189 if (!m_window
) return FALSE
;
1192 // transform the source DC coords to the device ones
1193 xsrc
= source
->XLOG2DEV(xsrc
);
1194 ysrc
= source
->YLOG2DEV(ysrc
);
1197 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1198 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1200 bool use_bitmap_method
= FALSE
;
1201 bool is_mono
= FALSE
;
1203 /* TODO: use the mask origin when drawing transparently */
1204 if (xsrcMask
== -1 && ysrcMask
== -1)
1206 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1209 if (srcDC
->m_isMemDC
)
1211 if (!memDC
->m_selected
.Ok()) return FALSE
;
1213 /* we use the "XCopyArea" way to copy a memory dc into
1214 y different window if the memory dc BOTH
1215 a) doesn't have any mask or its mask isn't used
1219 if (useMask
&& (memDC
->m_selected
.GetMask()))
1221 /* we HAVE TO use the direct way for memory dcs
1222 that have mask since the XCopyArea doesn't know
1224 use_bitmap_method
= TRUE
;
1226 else if (memDC
->m_selected
.GetDepth() == 1)
1228 /* we HAVE TO use the direct way for memory dcs
1229 that are bitmaps because XCopyArea doesn't cope
1230 with different bit depths */
1232 use_bitmap_method
= TRUE
;
1234 else if ((xsrc
== 0) && (ysrc
== 0) &&
1235 (width
== memDC
->m_selected
.GetWidth()) &&
1236 (height
== memDC
->m_selected
.GetHeight()))
1238 /* we SHOULD use the direct way if all of the bitmap
1239 in the memory dc is copied in which case XCopyArea
1240 wouldn't be able able to boost performace by reducing
1241 the area to be scaled */
1242 use_bitmap_method
= TRUE
;
1246 use_bitmap_method
= FALSE
;
1250 CalcBoundingBox( xdest
, ydest
);
1251 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1253 /* scale/translate size and position */
1254 wxCoord xx
= XLOG2DEV(xdest
);
1255 wxCoord yy
= YLOG2DEV(ydest
);
1257 wxCoord ww
= XLOG2DEVREL(width
);
1258 wxCoord hh
= YLOG2DEVREL(height
);
1260 /* compare to current clipping region */
1261 if (!m_currentClippingRegion
.IsNull())
1263 wxRegion
tmp( xx
,yy
,ww
,hh
);
1264 tmp
.Intersect( m_currentClippingRegion
);
1269 int old_logical_func
= m_logicalFunction
;
1270 SetLogicalFunction( logical_func
);
1272 if (use_bitmap_method
)
1274 /* scale/translate bitmap size */
1275 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1276 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1278 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1279 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1281 /* scale bitmap if required */
1282 wxBitmap use_bitmap
;
1284 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1286 wxImage image
= memDC
->m_selected
.ConvertToImage();
1287 image
= image
.Scale( bm_ww
, bm_hh
);
1290 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1292 use_bitmap
= wxBitmap(image
);
1296 use_bitmap
= memDC
->m_selected
;
1299 /* apply mask if any */
1300 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1301 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1303 if (useMask
&& mask
)
1305 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1306 #ifndef __WXGTK20__ // TODO fix crash
1307 if (!m_currentClippingRegion
.IsNull())
1310 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1311 GdkGC
*gc
= gdk_gc_new( new_mask
);
1313 gdk_gc_set_foreground( gc
, &col
);
1314 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1316 gdk_gc_set_background( gc
, &col
);
1318 gdk_gc_set_foreground( gc
, &col
);
1319 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1320 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1321 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1322 gdk_gc_set_stipple( gc
, mask
);
1323 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1330 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1332 gdk_gc_set_clip_mask( m_textGC
, mask
);
1333 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1338 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1340 gdk_gc_set_clip_mask( m_penGC
, mask
);
1341 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1344 gdk_bitmap_unref( new_mask
);
1347 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1348 drawing a mono-bitmap (XBitmap) we use the current text GC */
1351 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1353 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1355 /* remove mask again if any */
1356 if (useMask
&& mask
)
1360 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1361 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1362 if (!m_currentClippingRegion
.IsNull())
1363 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1367 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1368 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1369 if (!m_currentClippingRegion
.IsNull())
1370 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1374 else /* use_bitmap_method */
1376 if ((width
!= ww
) || (height
!= hh
))
1378 /* draw source window into a bitmap as we cannot scale
1379 a window in contrast to a bitmap. this would actually
1380 work with memory dcs as well, but we'd lose the mask
1381 information and waste one step in this process since
1382 a memory already has a bitmap. all this is slightly
1383 inefficient as we could take an XImage directly from
1384 an X window, but we'd then also have to care that
1385 the window is not outside the screen (in which case
1386 we'd get a BadMatch or what not).
1387 Is a double XGetImage and combined XGetPixel and
1388 XPutPixel really faster? I'm not sure. look at wxXt
1389 for a different implementation of the same problem. */
1391 wxBitmap
bitmap( width
, height
);
1393 /* copy including child window contents */
1394 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1395 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1397 xsrc
, ysrc
, width
, height
);
1398 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1401 wxImage image
= bitmap
.ConvertToImage();
1402 image
= image
.Scale( ww
, hh
);
1404 /* convert to bitmap */
1405 bitmap
= wxBitmap(image
);
1407 /* draw scaled bitmap */
1408 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1413 /* No scaling and not a memory dc with a mask either */
1415 /* copy including child window contents */
1416 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1417 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1419 xsrc
, ysrc
, width
, height
);
1420 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1424 SetLogicalFunction( old_logical_func
);
1428 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1430 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1432 if (!m_window
) return;
1434 if (text
.empty()) return;
1437 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1439 wxCHECK_RET( font
, wxT("invalid font") );
1446 wxCHECK_RET( m_context
, wxT("no Pango context") );
1447 wxCHECK_RET( m_layout
, wxT("no Pango layout") );
1448 wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") );
1451 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( text
);
1453 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( text
);
1454 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1456 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1460 if (m_scaleY
!= 1.0)
1462 // If there is a user or actually any scale applied to
1463 // the device context, scale the font.
1465 // scale font description
1466 gint oldSize
= pango_font_description_get_size( m_fontdesc
);
1467 double size
= oldSize
;
1468 size
= size
* m_scaleY
;
1469 pango_font_description_set_size( m_fontdesc
, (gint
)size
);
1471 // actually apply scaled font
1472 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1474 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1475 if ( m_backgroundMode
== wxSOLID
)
1477 gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor());
1478 gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
);
1479 gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor());
1483 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1485 // reset unscaled size
1486 pango_font_description_set_size( m_fontdesc
, oldSize
);
1488 // actually apply unscaled font
1489 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1493 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1494 if ( m_backgroundMode
== wxSOLID
)
1496 gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor());
1497 gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
);
1498 gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor());
1501 gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout
);
1508 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1509 wxCoord height
= font
->ascent
+ font
->descent
;
1511 if ( m_backgroundMode
== wxSOLID
)
1513 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1514 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1515 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1517 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1519 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1520 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1521 properties (see wxXt implementation) */
1522 if (m_font
.GetUnderlined())
1524 wxCoord ul_y
= y
+ font
->ascent
;
1525 if (font
->descent
> 0) ul_y
++;
1526 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1528 #endif // GTK+ 2.0/1.x
1530 width
= wxCoord(width
/ m_scaleX
);
1531 height
= wxCoord(height
/ m_scaleY
);
1532 CalcBoundingBox (x
+ width
, y
+ height
);
1533 CalcBoundingBox (x
, y
);
1536 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1540 DrawText(text
, x
, y
);
1544 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1546 if (!m_window
) return;
1549 // implement later without GdkFont for GTK 2.0
1552 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1554 wxCHECK_RET( font
, wxT("invalid font") );
1556 // the size of the text
1557 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1558 wxCoord h
= font
->ascent
+ font
->descent
;
1560 // draw the string normally
1563 dc
.SelectObject(src
);
1564 dc
.SetFont(GetFont());
1565 dc
.SetBackground(*wxWHITE_BRUSH
);
1566 dc
.SetBrush(*wxBLACK_BRUSH
);
1568 dc
.DrawText(text
, 0, 0);
1569 dc
.SelectObject(wxNullBitmap
);
1571 // Calculate the size of the rotated bounding box.
1572 double rad
= DegToRad(angle
);
1573 double dx
= cos(rad
),
1576 // the rectngle vertices are counted clockwise with the first one being at
1577 // (0, 0) (or, rather, at (x, y))
1579 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1582 double x3
= x4
+ x2
,
1586 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1587 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1588 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1589 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1591 // prepare to blit-with-rotate the bitmap to the DC
1592 wxImage image
= src
.ConvertToImage();
1594 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1595 *colBack
= m_textBackgroundColour
.GetColor();
1597 bool textColSet
= TRUE
;
1599 unsigned char *data
= image
.GetData();
1601 // paint pixel by pixel
1602 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1604 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1606 // transform source coords to dest coords
1607 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1608 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1609 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1610 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1613 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1614 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1616 // change colour if needed
1617 if ( textPixel
!= textColSet
)
1619 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1622 textColSet
= textPixel
;
1625 // don't use DrawPoint() because it uses the current pen
1626 // colour, and we don't need it here
1627 gdk_draw_point( m_window
, m_textGC
,
1628 XLOG2DEV(x
) + dstX
, YLOG2DEV(y
) + dstY
);
1633 // it would be better to draw with non underlined font and draw the line
1634 // manually here (it would be more straight...)
1636 if ( m_font
.GetUnderlined() )
1638 gdk_draw_line( m_window
, m_textGC
,
1639 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1640 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1644 // restore the font colour
1645 gdk_gc_set_foreground( m_textGC
, colText
);
1647 // update the bounding box
1648 CalcBoundingBox(x
+ minX
, y
+ minY
);
1649 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1653 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1654 wxCoord
*width
, wxCoord
*height
,
1655 wxCoord
*descent
, wxCoord
*externalLeading
,
1656 wxFont
*theFont
) const
1658 if (string
.IsEmpty())
1660 if (width
) (*width
) = 0;
1661 if (height
) (*height
) = 0;
1666 // Set new font description
1668 pango_layout_set_font_description( m_layout
, theFont
->GetNativeFontInfo()->description
);
1670 // Set layout's text
1672 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( string
);
1673 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1675 const wxWCharBuffer wdata
= wxConvLocal
.cMB2WC( string
);
1676 const wxCharBuffer data
= wxConvUTF8
.cWC2MB( wdata
);
1677 pango_layout_set_text( m_layout
, (const char*) data
, strlen( (const char*) data
));
1681 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1683 if (width
) (*width
) = (wxCoord
) w
;
1684 if (height
) (*height
) = (wxCoord
) h
;
1687 // Do something about metrics here. TODO.
1690 if (externalLeading
) (*externalLeading
) = 0; // ??
1692 // Reset old font description
1694 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1696 wxFont fontToUse
= m_font
;
1697 if (theFont
) fontToUse
= *theFont
;
1699 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1700 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1701 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1702 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1703 if (externalLeading
) (*externalLeading
) = 0; // ??
1707 wxCoord
wxWindowDC::GetCharWidth() const
1710 pango_layout_set_text( m_layout
, "H", 1 );
1712 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1715 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1716 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1718 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1722 wxCoord
wxWindowDC::GetCharHeight() const
1725 pango_layout_set_text( m_layout
, "H", 1 );
1727 pango_layout_get_pixel_size( m_layout
, &w
, &h
);
1730 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1731 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1733 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1737 void wxWindowDC::Clear()
1739 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1741 if (!m_window
) return;
1743 // VZ: the code below results in infinite recursion and crashes when
1744 // dc.Clear() is done from OnPaint() so I disable it for now.
1745 // I don't know what the correct fix is but Clear() surely should not
1746 // reenter OnPaint()!
1748 /* - we either are a memory dc or have a window as the
1749 owner. anything else shouldn't happen.
1750 - we don't use gdk_window_clear() as we don't set
1751 the window's background colour anymore. it is too
1752 much pain to keep the DC's and the window's back-
1753 ground colour in synch. */
1764 GetSize( &width
, &height
);
1765 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1770 GetSize( &width
, &height
);
1771 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1775 void wxWindowDC::SetFont( const wxFont
&font
)
1783 pango_font_description_free( m_fontdesc
);
1785 m_fontdesc
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description
);
1790 PangoContext
*oldContext
= m_context
;
1792 // We might want to use the X11 context for faster
1793 // rendering on screen
1794 if (m_font
.GetNoAntiAliasing())
1795 m_context
= m_owner
->GtkGetPangoX11Context();
1797 m_context
= m_owner
->GtkGetPangoDefaultContext();
1799 // If we switch back/forth between different contexts
1800 // we also have to create a new layout. I think so,
1801 // at least, and it doesn't hurt to do it.
1802 if (oldContext
!= m_context
)
1805 g_object_unref( G_OBJECT( m_layout
) );
1807 m_layout
= pango_layout_new( m_context
);
1811 pango_layout_set_font_description( m_layout
, m_fontdesc
);
1816 void wxWindowDC::SetPen( const wxPen
&pen
)
1818 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1820 if (m_pen
== pen
) return;
1824 if (!m_pen
.Ok()) return;
1826 if (!m_window
) return;
1828 gint width
= m_pen
.GetWidth();
1831 // CMB: if width is non-zero scale it with the dc
1836 // X doesn't allow different width in x and y and so we take
1839 ( fabs((double) XLOG2DEVREL(width
)) +
1840 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1844 // width can't be 0 or an internal GTK error occurs inside
1845 // gdk_gc_set_dashes() below
1850 static const wxGTKDash dotted
[] = {1, 1};
1851 static const wxGTKDash short_dashed
[] = {2, 2};
1852 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1853 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1855 // We express dash pattern in pen width unit, so we are
1856 // independent of zoom factor and so on...
1858 const wxGTKDash
*req_dash
;
1860 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1861 switch (m_pen
.GetStyle())
1865 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1866 req_nb_dash
= m_pen
.GetDashCount();
1867 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1872 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1879 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1881 req_dash
= wxCoord_dashed
;
1886 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1888 req_dash
= short_dashed
;
1893 // lineStyle = GDK_LINE_DOUBLE_DASH;
1894 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1896 req_dash
= dotted_dashed
;
1901 case wxSTIPPLE_MASK_OPAQUE
:
1906 lineStyle
= GDK_LINE_SOLID
;
1907 req_dash
= (wxGTKDash
*)NULL
;
1913 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1914 if (req_dash
&& req_nb_dash
)
1916 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1919 for (int i
= 0; i
< req_nb_dash
; i
++)
1920 real_req_dash
[i
] = req_dash
[i
] * width
;
1921 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1922 delete[] real_req_dash
;
1926 // No Memory. We use non-scaled dash pattern...
1927 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1930 #endif // GTK+ > 1.0
1932 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1933 switch (m_pen
.GetCap())
1935 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1936 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1943 capStyle
= GDK_CAP_NOT_LAST
;
1947 capStyle
= GDK_CAP_ROUND
;
1953 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1954 switch (m_pen
.GetJoin())
1956 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1957 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1959 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1962 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1964 m_pen
.GetColour().CalcPixel( m_cmap
);
1965 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1968 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1970 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1972 if (m_brush
== brush
) return;
1976 if (!m_brush
.Ok()) return;
1978 if (!m_window
) return;
1980 m_brush
.GetColour().CalcPixel( m_cmap
);
1981 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1983 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1985 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1987 if (m_brush
.GetStipple()->GetPixmap())
1989 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1990 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1994 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1995 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1999 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
2001 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
2002 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
2005 if (IS_HATCH(m_brush
.GetStyle()))
2007 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
2008 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
2009 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
2013 void wxWindowDC::SetBackground( const wxBrush
&brush
)
2015 /* CMB 21/7/98: Added SetBackground. Sets background brush
2016 * for Clear() and bg colour for shapes filled with cross-hatch brush */
2018 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2020 if (m_backgroundBrush
== brush
) return;
2022 m_backgroundBrush
= brush
;
2024 if (!m_backgroundBrush
.Ok()) return;
2026 if (!m_window
) return;
2028 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
2029 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
2030 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
2031 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2032 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
2034 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
2036 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
2038 if (m_backgroundBrush
.GetStipple()->GetPixmap())
2040 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
2041 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
2045 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2046 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
2050 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
2052 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
2053 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
2054 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
2058 void wxWindowDC::SetLogicalFunction( int function
)
2060 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2062 if (m_logicalFunction
== function
)
2065 // VZ: shouldn't this be a CHECK?
2072 case wxXOR
: mode
= GDK_XOR
; break;
2073 case wxINVERT
: mode
= GDK_INVERT
; break;
2074 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
2075 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
2076 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
2077 case wxCLEAR
: mode
= GDK_CLEAR
; break;
2078 case wxSET
: mode
= GDK_SET
; break;
2079 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
2080 case wxAND
: mode
= GDK_AND
; break;
2081 case wxOR
: mode
= GDK_OR
; break;
2082 case wxEQUIV
: mode
= GDK_EQUIV
; break;
2083 case wxNAND
: mode
= GDK_NAND
; break;
2084 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
2085 case wxCOPY
: mode
= GDK_COPY
; break;
2086 case wxNO_OP
: mode
= GDK_NOOP
; break;
2087 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
2089 // unsupported by GTK
2090 case wxNOR
: mode
= GDK_COPY
; break;
2091 #endif // GTK+ > 1.0
2093 wxFAIL_MSG( wxT("unsupported logical function") );
2097 m_logicalFunction
= function
;
2099 gdk_gc_set_function( m_penGC
, mode
);
2100 gdk_gc_set_function( m_brushGC
, mode
);
2102 // to stay compatible with wxMSW, we don't apply ROPs to the text
2103 // operations (i.e. DrawText/DrawRotatedText).
2104 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2105 gdk_gc_set_function( m_textGC
, mode
);
2108 void wxWindowDC::SetTextForeground( const wxColour
&col
)
2110 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2112 // don't set m_textForegroundColour to an invalid colour as we'd crash
2113 // later then (we use m_textForegroundColour.GetColor() without checking
2115 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
2118 m_textForegroundColour
= col
;
2122 m_textForegroundColour
.CalcPixel( m_cmap
);
2123 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
2127 void wxWindowDC::SetTextBackground( const wxColour
&col
)
2129 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2132 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
2135 m_textBackgroundColour
= col
;
2139 m_textBackgroundColour
.CalcPixel( m_cmap
);
2140 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
2144 void wxWindowDC::SetBackgroundMode( int mode
)
2146 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2148 m_backgroundMode
= mode
;
2150 if (!m_window
) return;
2152 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2153 // transparent/solid background mode
2155 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
2157 gdk_gc_set_fill( m_brushGC
,
2158 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
2162 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
2164 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
2167 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
2169 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2171 if (!m_window
) return;
2174 rect
.x
= XLOG2DEV(x
);
2175 rect
.y
= YLOG2DEV(y
);
2176 rect
.width
= XLOG2DEVREL(width
);
2177 rect
.height
= YLOG2DEVREL(height
);
2179 if (!m_currentClippingRegion
.IsNull())
2180 m_currentClippingRegion
.Intersect( rect
);
2182 m_currentClippingRegion
.Union( rect
);
2184 #if USE_PAINT_REGION
2185 if (!m_paintClippingRegion
.IsNull())
2186 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2189 wxCoord xx
, yy
, ww
, hh
;
2190 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2191 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2193 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2194 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2195 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2196 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2199 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2201 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2205 DestroyClippingRegion();
2209 if (!m_window
) return;
2211 if (!m_currentClippingRegion
.IsNull())
2212 m_currentClippingRegion
.Intersect( region
);
2214 m_currentClippingRegion
.Union( region
);
2216 #if USE_PAINT_REGION
2217 if (!m_paintClippingRegion
.IsNull())
2218 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2221 wxCoord xx
, yy
, ww
, hh
;
2222 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2223 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
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() );
2231 void wxWindowDC::DestroyClippingRegion()
2233 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2235 wxDC::DestroyClippingRegion();
2237 m_currentClippingRegion
.Clear();
2239 #if USE_PAINT_REGION
2240 if (!m_paintClippingRegion
.IsEmpty())
2241 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2244 if (!m_window
) return;
2246 if (m_currentClippingRegion
.IsEmpty())
2248 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2249 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2250 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2251 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2255 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2256 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2257 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2258 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2262 void wxWindowDC::Destroy()
2264 if (m_penGC
) wxFreePoolGC( m_penGC
);
2265 m_penGC
= (GdkGC
*) NULL
;
2266 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2267 m_brushGC
= (GdkGC
*) NULL
;
2268 if (m_textGC
) wxFreePoolGC( m_textGC
);
2269 m_textGC
= (GdkGC
*) NULL
;
2270 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2271 m_bgGC
= (GdkGC
*) NULL
;
2274 void wxWindowDC::ComputeScaleAndOrigin()
2276 /* CMB: copy scale to see if it changes */
2277 double origScaleX
= m_scaleX
;
2278 double origScaleY
= m_scaleY
;
2280 wxDC::ComputeScaleAndOrigin();
2282 /* CMB: if scale has changed call SetPen to recalulate the line width */
2283 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2286 /* this is a bit artificial, but we need to force wxDC to think
2287 the pen has changed */
2294 // Resolution in pixels per logical inch
2295 wxSize
wxWindowDC::GetPPI() const
2297 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2300 int wxWindowDC::GetDepth() const
2302 wxFAIL_MSG(wxT("not implemented"));
2308 //-----------------------------------------------------------------------------
2310 //-----------------------------------------------------------------------------
2312 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2314 wxPaintDC::wxPaintDC( wxWindow
*win
)
2317 #if USE_PAINT_REGION
2318 if (!win
->m_clipPaintRegion
)
2321 m_paintClippingRegion
= win
->GetUpdateRegion();
2322 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2325 m_paintClippingRegion
= win
->GetUpdateRegion();
2326 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2329 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2331 gdk_gc_set_clip_region( m_penGC
, region
);
2332 gdk_gc_set_clip_region( m_brushGC
, region
);
2333 gdk_gc_set_clip_region( m_textGC
, region
);
2334 gdk_gc_set_clip_region( m_bgGC
, region
);
2337 #endif // USE_PAINT_REGION
2340 //-----------------------------------------------------------------------------
2342 //-----------------------------------------------------------------------------
2344 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2346 wxClientDC::wxClientDC( wxWindow
*win
)
2349 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2351 #ifdef __WXUNIVERSAL__
2352 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2353 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2354 wxSize size
= win
->GetClientSize();
2355 SetClippingRegion(wxPoint(0, 0), size
);
2356 #endif // __WXUNIVERSAL__
2359 void wxClientDC::DoGetSize(int *width
, int *height
) const
2361 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2363 m_owner
->GetClientSize( width
, height
);
2366 // ----------------------------------------------------------------------------
2368 // ----------------------------------------------------------------------------
2370 class wxDCModule
: public wxModule
2377 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2380 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2382 bool wxDCModule::OnInit()
2388 void wxDCModule::OnExit()