]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/dcclient.cpp
929d71bfb9610f967990ca4c57db65e8c492377f
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"
24 #include "wx/gtk/win_gtk.h"
26 #include <math.h> // for floating-point functions
30 #include <gdk/gdkprivate.h>
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
37 #define USE_PAINT_REGION 1
39 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
51 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
52 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
55 static GdkPixmap
*hatches
[num_hatches
];
56 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
58 extern GtkWidget
*wxGetRootWindow();
60 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
64 const double RAD2DEG
= 180.0 / M_PI
;
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
71 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
73 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
75 //-----------------------------------------------------------------------------
76 // temporary implementation of the missing GDK function
77 //-----------------------------------------------------------------------------
79 #include "gdk/gdkprivate.h"
81 void gdk_wx_draw_bitmap(GdkDrawable
*drawable
,
91 gint src_width
, src_height
;
93 GdkWindowPrivate
*drawable_private
;
94 GdkWindowPrivate
*src_private
;
95 GdkGCPrivate
*gc_private
;
98 g_return_if_fail (drawable
!= NULL
);
99 g_return_if_fail (src
!= NULL
);
100 g_return_if_fail (gc
!= NULL
);
103 if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
))
106 gdk_drawable_get_size(src
, &src_width
, &src_height
);
108 drawable_private
= (GdkWindowPrivate
*) drawable
;
109 src_private
= (GdkWindowPrivate
*) src
;
110 if (drawable_private
->destroyed
|| src_private
->destroyed
)
113 src_width
= src_private
->width
;
114 src_height
= src_private
->height
;
116 gc_private
= (GdkGCPrivate
*) gc
;
119 if (width
== -1) width
= src_width
;
120 if (height
== -1) height
= src_height
;
123 XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
),
125 GDK_WINDOW_XID(drawable
),
132 XCopyPlane( drawable_private
->xdisplay
,
133 src_private
->xwindow
,
134 drawable_private
->xwindow
,
143 //-----------------------------------------------------------------------------
144 // Implement Pool of Graphic contexts. Creating them takes too much time.
145 //-----------------------------------------------------------------------------
147 #define GC_POOL_SIZE 200
173 static wxGC wxGCPool
[GC_POOL_SIZE
];
175 static void wxInitGCPool()
177 memset( wxGCPool
, 0, GC_POOL_SIZE
*sizeof(wxGC
) );
180 static void wxCleanUpGCPool()
182 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
184 if (wxGCPool
[i
].m_gc
)
185 gdk_gc_unref( wxGCPool
[i
].m_gc
);
189 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
191 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
193 if (!wxGCPool
[i
].m_gc
)
195 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
196 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
197 wxGCPool
[i
].m_type
= type
;
198 wxGCPool
[i
].m_used
= FALSE
;
200 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
202 wxGCPool
[i
].m_used
= TRUE
;
203 return wxGCPool
[i
].m_gc
;
207 wxFAIL_MSG( wxT("No GC available") );
209 return (GdkGC
*) NULL
;
212 static void wxFreePoolGC( GdkGC
*gc
)
214 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
216 if (wxGCPool
[i
].m_gc
== gc
)
218 wxGCPool
[i
].m_used
= FALSE
;
223 wxFAIL_MSG( wxT("Wrong GC") );
226 //-----------------------------------------------------------------------------
228 //-----------------------------------------------------------------------------
230 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
232 wxWindowDC::wxWindowDC()
234 m_penGC
= (GdkGC
*) NULL
;
235 m_brushGC
= (GdkGC
*) NULL
;
236 m_textGC
= (GdkGC
*) NULL
;
237 m_bgGC
= (GdkGC
*) NULL
;
238 m_cmap
= (GdkColormap
*) NULL
;
240 m_isScreenDC
= FALSE
;
241 m_owner
= (wxWindow
*)NULL
;
243 m_context
= (PangoContext
*)NULL
;
244 m_fontdesc
= (PangoFontDescription
*)NULL
;
248 wxWindowDC::wxWindowDC( wxWindow
*window
)
250 wxASSERT_MSG( window
, wxT("DC needs a window") );
252 m_penGC
= (GdkGC
*) NULL
;
253 m_brushGC
= (GdkGC
*) NULL
;
254 m_textGC
= (GdkGC
*) NULL
;
255 m_bgGC
= (GdkGC
*) NULL
;
256 m_cmap
= (GdkColormap
*) NULL
;
257 m_owner
= (wxWindow
*)NULL
;
259 m_isScreenDC
= FALSE
;
260 m_font
= window
->GetFont();
262 GtkWidget
*widget
= window
->m_wxwindow
;
264 // some controls don't have m_wxwindow - like wxStaticBox, but the user
265 // code should still be able to create wxClientDCs for them, so we will
266 // use the parent window here then
269 window
= window
->GetParent();
270 widget
= window
->m_wxwindow
;
273 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
276 m_context
= gtk_widget_get_pango_context( widget
);
277 m_fontdesc
= widget
->style
->font_desc
;
280 GtkPizza
*pizza
= GTK_PIZZA( widget
);
281 m_window
= pizza
->bin_window
;
286 /* don't report problems */
292 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
296 /* this must be done after SetUpDC, bacause SetUpDC calls the
297 repective SetBrush, SetPen, SetBackground etc functions
298 to set up the DC. SetBackground call m_owner->SetBackground
299 and this might not be desired as the standard dc background
300 is white whereas a window might assume gray to be the
301 standard (as e.g. wxStatusBar) */
306 wxWindowDC::~wxWindowDC()
311 void wxWindowDC::SetUpDC()
315 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
319 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
320 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
321 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
322 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
325 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
327 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
328 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
329 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
330 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
334 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
335 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
336 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
337 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
340 /* background colour */
341 m_backgroundBrush
= *wxWHITE_BRUSH
;
342 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
343 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
346 m_textForegroundColour
.CalcPixel( m_cmap
);
347 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
349 m_textBackgroundColour
.CalcPixel( m_cmap
);
350 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
352 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
355 m_pen
.GetColour().CalcPixel( m_cmap
);
356 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
357 gdk_gc_set_background( m_penGC
, bg_col
);
359 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
362 m_brush
.GetColour().CalcPixel( m_cmap
);
363 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
364 gdk_gc_set_background( m_brushGC
, bg_col
);
366 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
369 gdk_gc_set_background( m_bgGC
, bg_col
);
370 gdk_gc_set_foreground( m_bgGC
, bg_col
);
372 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
375 gdk_gc_set_function( m_textGC
, GDK_COPY
);
376 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
377 gdk_gc_set_function( m_penGC
, GDK_COPY
);
380 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
381 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
382 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
383 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
387 hatch_bitmap
= hatches
;
388 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
389 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
390 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
391 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
392 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
393 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
397 void wxWindowDC::DoGetSize( int* width
, int* height
) const
399 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
401 m_owner
->GetSize(width
, height
);
404 void wxWindowDC::DoFloodFill( wxCoord x
, wxCoord y
,
405 const wxColour
& col
, int style
)
407 if (GetBrush().GetStyle() == wxTRANSPARENT
)
409 wxLogDebug(wxT("In FloodFill, current Brush is transparent, no filling done"));
414 this->GetSize(&width
, &height
);
415 //it would be nice to fail if we don't get a sensible size...
416 if (width
< 1 || height
< 1)
418 wxLogError(wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC"));
422 //this is much faster than doing the individual pixels
424 wxBitmap
bitmap(width
, height
);
425 memdc
.SelectObject(bitmap
);
426 memdc
.Blit(0, 0, width
, height
, (wxDC
*) this, 0, 0);
427 memdc
.SelectObject(wxNullBitmap
);
429 wxImage image
= bitmap
.ConvertToImage();
430 image
.DoFloodFill (x
,y
, GetBrush(), col
, style
, GetLogicalFunction());
431 bitmap
= wxBitmap(image
);
432 memdc
.SelectObject(bitmap
);
433 Blit(0, 0, width
, height
, &memdc
, 0, 0);
434 memdc
.SelectObject(wxNullBitmap
);
437 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
439 // Generic (and therefore rather inefficient) method.
440 // Could be improved.
442 wxBitmap
bitmap(1, 1);
443 memdc
.SelectObject(bitmap
);
444 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
445 memdc
.SelectObject(wxNullBitmap
);
447 wxImage image
= bitmap
.ConvertToImage();
448 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
452 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
454 wxCHECK_RET( Ok(), wxT("invalid window dc") );
456 if (m_pen
.GetStyle() != wxTRANSPARENT
)
459 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
461 CalcBoundingBox(x1
, y1
);
462 CalcBoundingBox(x2
, y2
);
466 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
468 wxCHECK_RET( Ok(), wxT("invalid window dc") );
470 if (m_pen
.GetStyle() != wxTRANSPARENT
)
475 wxCoord xx
= XLOG2DEV(x
);
476 wxCoord yy
= YLOG2DEV(y
);
479 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
480 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
485 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
486 wxCoord xc
, wxCoord yc
)
488 wxCHECK_RET( Ok(), wxT("invalid window dc") );
490 wxCoord xx1
= XLOG2DEV(x1
);
491 wxCoord yy1
= YLOG2DEV(y1
);
492 wxCoord xx2
= XLOG2DEV(x2
);
493 wxCoord yy2
= YLOG2DEV(y2
);
494 wxCoord xxc
= XLOG2DEV(xc
);
495 wxCoord yyc
= YLOG2DEV(yc
);
496 double dx
= xx1
- xxc
;
497 double dy
= yy1
- yyc
;
498 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
499 wxCoord r
= (wxCoord
)radius
;
500 double radius1
, radius2
;
502 if (xx1
== xx2
&& yy1
== yy2
)
510 radius1
= radius2
= 0.0;
514 radius1
= (xx1
- xxc
== 0) ?
515 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
516 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
517 radius2
= (xx2
- xxc
== 0) ?
518 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
519 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
521 wxCoord alpha1
= wxCoord(radius1
* 64.0);
522 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
523 while (alpha2
<= 0) alpha2
+= 360*64;
524 while (alpha1
> 360*64) alpha1
-= 360*64;
528 if (m_brush
.GetStyle() != wxTRANSPARENT
)
530 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
532 gdk_gc_set_ts_origin( m_textGC
,
533 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
534 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
535 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
536 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
538 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
540 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
541 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
542 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
544 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
546 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
547 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
548 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
550 if (m_brush
.GetStyle() == wxSTIPPLE
)
552 gdk_gc_set_ts_origin( m_brushGC
,
553 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
554 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
555 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
556 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
560 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
564 if (m_pen
.GetStyle() != wxTRANSPARENT
)
566 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
568 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
569 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
573 CalcBoundingBox (x1
, y1
);
574 CalcBoundingBox (x2
, y2
);
577 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
579 wxCHECK_RET( Ok(), wxT("invalid window dc") );
581 wxCoord xx
= XLOG2DEV(x
);
582 wxCoord yy
= YLOG2DEV(y
);
583 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
584 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
586 // CMB: handle -ve width and/or height
587 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
588 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
592 wxCoord start
= wxCoord(sa
* 64.0);
593 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
595 if (m_brush
.GetStyle() != wxTRANSPARENT
)
597 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
599 gdk_gc_set_ts_origin( m_textGC
,
600 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
601 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
602 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
603 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
605 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
607 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
608 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
609 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
611 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
613 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
614 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
615 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
617 if (m_brush
.GetStyle() == wxSTIPPLE
)
619 gdk_gc_set_ts_origin( m_brushGC
,
620 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
621 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
622 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
623 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
627 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
631 if (m_pen
.GetStyle() != wxTRANSPARENT
)
632 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
635 CalcBoundingBox (x
, y
);
636 CalcBoundingBox (x
+ width
, y
+ height
);
639 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
641 wxCHECK_RET( Ok(), wxT("invalid window dc") );
643 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
644 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
646 CalcBoundingBox (x
, y
);
649 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
651 wxCHECK_RET( Ok(), wxT("invalid window dc") );
653 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
656 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
658 for (int i
= 0; i
< n
-1; i
++)
660 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
661 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
662 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
663 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
666 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
668 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
672 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
674 wxCHECK_RET( Ok(), wxT("invalid window dc") );
678 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
680 for (i
= 0 ; i
< n
; i
++)
682 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
683 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
685 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
690 if (m_brush
.GetStyle() != wxTRANSPARENT
)
692 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
694 gdk_gc_set_ts_origin( m_textGC
,
695 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
696 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
697 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
698 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
700 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
702 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
703 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
704 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
706 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
708 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
709 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
710 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
712 if (m_brush
.GetStyle() == wxSTIPPLE
)
714 gdk_gc_set_ts_origin( m_brushGC
,
715 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
716 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
717 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
718 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
722 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
726 if (m_pen
.GetStyle() != wxTRANSPARENT
)
728 for (i
= 0 ; i
< n
; i
++)
730 gdk_draw_line( m_window
, m_penGC
,
733 gdkpoints
[(i
+1)%n
].x
,
734 gdkpoints
[(i
+1)%n
].y
);
742 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
744 wxCHECK_RET( Ok(), wxT("invalid window dc") );
746 wxCoord xx
= XLOG2DEV(x
);
747 wxCoord yy
= YLOG2DEV(y
);
748 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
749 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
751 // CMB: draw nothing if transformed w or h is 0
752 if (ww
== 0 || hh
== 0) return;
754 // CMB: handle -ve width and/or height
755 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
756 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
760 if (m_brush
.GetStyle() != wxTRANSPARENT
)
762 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
764 gdk_gc_set_ts_origin( m_textGC
,
765 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
766 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
767 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
768 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
770 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
772 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
773 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
774 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
776 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
778 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
779 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
780 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
782 if (m_brush
.GetStyle() == wxSTIPPLE
)
784 gdk_gc_set_ts_origin( m_brushGC
,
785 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
786 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
787 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
788 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
792 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
796 if (m_pen
.GetStyle() != wxTRANSPARENT
)
797 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
800 CalcBoundingBox( x
, y
);
801 CalcBoundingBox( x
+ width
, y
+ height
);
804 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
806 wxCHECK_RET( Ok(), wxT("invalid window dc") );
808 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
810 wxCoord xx
= XLOG2DEV(x
);
811 wxCoord yy
= YLOG2DEV(y
);
812 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
813 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
814 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
816 // CMB: handle -ve width and/or height
817 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
818 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
820 // CMB: if radius is zero use DrawRectangle() instead to avoid
821 // X drawing errors with small radii
824 DrawRectangle( x
, y
, width
, height
);
828 // CMB: draw nothing if transformed w or h is 0
829 if (ww
== 0 || hh
== 0) return;
831 // CMB: adjust size if outline is drawn otherwise the result is
832 // 1 pixel too wide and high
833 if (m_pen
.GetStyle() != wxTRANSPARENT
)
841 // CMB: ensure dd is not larger than rectangle otherwise we
842 // get an hour glass shape
844 if (dd
> ww
) dd
= ww
;
845 if (dd
> hh
) dd
= hh
;
848 if (m_brush
.GetStyle() != wxTRANSPARENT
)
850 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
852 gdk_gc_set_ts_origin( m_textGC
,
853 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
854 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
855 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
856 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
857 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
858 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
859 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
860 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
861 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
863 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
865 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
866 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
867 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
868 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
869 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
870 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
871 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
872 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
874 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
876 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
877 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
878 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
879 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
880 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
881 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
882 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
883 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
885 if (m_brush
.GetStyle() == wxSTIPPLE
)
887 gdk_gc_set_ts_origin( m_brushGC
,
888 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
889 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
890 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
891 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
892 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
893 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
894 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
895 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
896 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
900 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
901 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
902 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
903 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
904 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
905 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
909 if (m_pen
.GetStyle() != wxTRANSPARENT
)
911 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
912 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
913 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
914 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
915 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
916 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
917 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
918 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
922 // this ignores the radius
923 CalcBoundingBox( x
, y
);
924 CalcBoundingBox( x
+ width
, y
+ height
);
927 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
929 wxCHECK_RET( Ok(), wxT("invalid window dc") );
931 wxCoord xx
= XLOG2DEV(x
);
932 wxCoord yy
= YLOG2DEV(y
);
933 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
934 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
936 // CMB: handle -ve width and/or height
937 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
938 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
942 if (m_brush
.GetStyle() != wxTRANSPARENT
)
944 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
946 gdk_gc_set_ts_origin( m_textGC
,
947 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
948 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
949 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
950 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
952 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
954 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
955 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
956 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
958 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
960 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
961 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
962 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
964 if (m_brush
.GetStyle() == wxSTIPPLE
)
966 gdk_gc_set_ts_origin( m_brushGC
,
967 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
968 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
969 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
970 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
974 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
978 if (m_pen
.GetStyle() != wxTRANSPARENT
)
979 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
982 CalcBoundingBox( x
, y
);
983 CalcBoundingBox( x
+ width
, y
+ height
);
986 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
988 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
989 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
992 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
993 wxCoord x
, wxCoord y
,
996 wxCHECK_RET( Ok(), wxT("invalid window dc") );
998 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
1000 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
1002 /* scale/translate size and position */
1003 int xx
= XLOG2DEV(x
);
1004 int yy
= YLOG2DEV(y
);
1006 int w
= bitmap
.GetWidth();
1007 int h
= bitmap
.GetHeight();
1009 CalcBoundingBox( x
, y
);
1010 CalcBoundingBox( x
+ w
, y
+ h
);
1012 if (!m_window
) return;
1014 int ww
= XLOG2DEVREL(w
);
1015 int hh
= YLOG2DEVREL(h
);
1017 /* compare to current clipping region */
1018 if (!m_currentClippingRegion
.IsNull())
1020 wxRegion
tmp( xx
,yy
,ww
,hh
);
1021 tmp
.Intersect( m_currentClippingRegion
);
1026 /* scale bitmap if required */
1027 wxBitmap use_bitmap
;
1028 if ((w
!= ww
) || (h
!= hh
))
1030 wxImage image
= bitmap
.ConvertToImage();
1031 image
.Rescale( ww
, hh
);
1033 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1035 use_bitmap
= wxBitmap(image
);
1039 use_bitmap
= bitmap
;
1042 /* apply mask if any */
1043 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1044 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1046 if (useMask
&& mask
)
1048 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1049 #ifndef __WXGTK20__ // TODO fix crash
1050 if (!m_currentClippingRegion
.IsNull())
1053 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1054 GdkGC
*gc
= gdk_gc_new( new_mask
);
1056 gdk_gc_set_foreground( gc
, &col
);
1057 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1059 gdk_gc_set_background( gc
, &col
);
1061 gdk_gc_set_foreground( gc
, &col
);
1062 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1063 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1064 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1065 gdk_gc_set_stipple( gc
, mask
);
1066 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1073 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1075 gdk_gc_set_clip_mask( m_textGC
, mask
);
1076 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1081 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1083 gdk_gc_set_clip_mask( m_penGC
, mask
);
1084 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1088 gdk_bitmap_unref( new_mask
);
1091 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1092 drawing a mono-bitmap (XBitmap) we use the current text GC */
1094 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1096 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1098 /* remove mask again if any */
1099 if (useMask
&& mask
)
1103 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1104 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1105 if (!m_currentClippingRegion
.IsNull())
1106 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1110 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1111 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1112 if (!m_currentClippingRegion
.IsNull())
1113 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1118 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1119 wxCoord width
, wxCoord height
,
1121 wxCoord xsrc
, wxCoord ysrc
,
1124 wxCoord xsrcMask
, wxCoord ysrcMask
)
1126 /* this is the nth try to get this utterly useless function to
1127 work. it now completely ignores the scaling or translation
1128 of the source dc, but scales correctly on the target dc and
1129 knows about possible mask information in a memory dc. */
1131 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1133 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1135 if (!m_window
) return FALSE
;
1138 // transform the source DC coords to the device ones
1139 xsrc
= source
->XLOG2DEV(xsrc
);
1140 ysrc
= source
->YLOG2DEV(ysrc
);
1143 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1144 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1146 bool use_bitmap_method
= FALSE
;
1147 bool is_mono
= FALSE
;
1149 /* TODO: use the mask origin when drawing transparently */
1150 if (xsrcMask
== -1 && ysrcMask
== -1)
1152 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1155 if (srcDC
->m_isMemDC
)
1157 if (!memDC
->m_selected
.Ok()) return FALSE
;
1159 /* we use the "XCopyArea" way to copy a memory dc into
1160 y different window if the memory dc BOTH
1161 a) doesn't have any mask or its mask isn't used
1165 if (useMask
&& (memDC
->m_selected
.GetMask()))
1167 /* we HAVE TO use the direct way for memory dcs
1168 that have mask since the XCopyArea doesn't know
1170 use_bitmap_method
= TRUE
;
1172 else if (memDC
->m_selected
.GetDepth() == 1)
1174 /* we HAVE TO use the direct way for memory dcs
1175 that are bitmaps because XCopyArea doesn't cope
1176 with different bit depths */
1178 use_bitmap_method
= TRUE
;
1180 else if ((xsrc
== 0) && (ysrc
== 0) &&
1181 (width
== memDC
->m_selected
.GetWidth()) &&
1182 (height
== memDC
->m_selected
.GetHeight()))
1184 /* we SHOULD use the direct way if all of the bitmap
1185 in the memory dc is copied in which case XCopyArea
1186 wouldn't be able able to boost performace by reducing
1187 the area to be scaled */
1188 use_bitmap_method
= TRUE
;
1192 use_bitmap_method
= FALSE
;
1196 CalcBoundingBox( xdest
, ydest
);
1197 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1199 /* scale/translate size and position */
1200 wxCoord xx
= XLOG2DEV(xdest
);
1201 wxCoord yy
= YLOG2DEV(ydest
);
1203 wxCoord ww
= XLOG2DEVREL(width
);
1204 wxCoord hh
= YLOG2DEVREL(height
);
1206 /* compare to current clipping region */
1207 if (!m_currentClippingRegion
.IsNull())
1209 wxRegion
tmp( xx
,yy
,ww
,hh
);
1210 tmp
.Intersect( m_currentClippingRegion
);
1215 int old_logical_func
= m_logicalFunction
;
1216 SetLogicalFunction( logical_func
);
1218 if (use_bitmap_method
)
1220 /* scale/translate bitmap size */
1221 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1222 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1224 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1225 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1227 /* scale bitmap if required */
1228 wxBitmap use_bitmap
;
1230 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1232 wxImage image
= memDC
->m_selected
.ConvertToImage();
1233 image
= image
.Scale( bm_ww
, bm_hh
);
1236 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1238 use_bitmap
= wxBitmap(image
);
1242 use_bitmap
= memDC
->m_selected
;
1245 /* apply mask if any */
1246 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1247 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1249 if (useMask
&& mask
)
1251 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1252 #ifndef __WXGTK20__ // TODO fix crash
1253 if (!m_currentClippingRegion
.IsNull())
1256 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1257 GdkGC
*gc
= gdk_gc_new( new_mask
);
1259 gdk_gc_set_foreground( gc
, &col
);
1260 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1262 gdk_gc_set_background( gc
, &col
);
1264 gdk_gc_set_foreground( gc
, &col
);
1265 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1266 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1267 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1268 gdk_gc_set_stipple( gc
, mask
);
1269 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1276 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1278 gdk_gc_set_clip_mask( m_textGC
, mask
);
1279 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1284 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1286 gdk_gc_set_clip_mask( m_penGC
, mask
);
1287 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1290 gdk_bitmap_unref( new_mask
);
1293 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1294 drawing a mono-bitmap (XBitmap) we use the current text GC */
1297 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1299 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1301 /* remove mask again if any */
1302 if (useMask
&& mask
)
1306 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1307 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1308 if (!m_currentClippingRegion
.IsNull())
1309 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1313 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1314 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1315 if (!m_currentClippingRegion
.IsNull())
1316 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1320 else /* use_bitmap_method */
1322 if ((width
!= ww
) || (height
!= hh
))
1324 /* draw source window into a bitmap as we cannot scale
1325 a window in contrast to a bitmap. this would actually
1326 work with memory dcs as well, but we'd lose the mask
1327 information and waste one step in this process since
1328 a memory already has a bitmap. all this is slightly
1329 inefficient as we could take an XImage directly from
1330 an X window, but we'd then also have to care that
1331 the window is not outside the screen (in which case
1332 we'd get a BadMatch or what not).
1333 Is a double XGetImage and combined XGetPixel and
1334 XPutPixel really faster? I'm not sure. look at wxXt
1335 for a different implementation of the same problem. */
1337 wxBitmap
bitmap( width
, height
);
1339 /* copy including child window contents */
1340 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1341 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1343 xsrc
, ysrc
, width
, height
);
1344 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1347 wxImage image
= bitmap
.ConvertToImage();
1348 image
= image
.Scale( ww
, hh
);
1350 /* convert to bitmap */
1351 bitmap
= wxBitmap(image
);
1353 /* draw scaled bitmap */
1354 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1359 /* No scaling and not a memory dc with a mask either */
1361 /* copy including child window contents */
1362 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1363 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1365 xsrc
, ysrc
, width
, height
);
1366 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1370 SetLogicalFunction( old_logical_func
);
1374 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1376 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1378 if (!m_window
) return;
1380 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1382 wxCHECK_RET( font
, wxT("invalid font") );
1384 #if defined(__WXGTK20__)
1385 wxCHECK_RET( m_context
, wxT("no Pango context") );
1391 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1392 // TODO: the layout engine should be abstracted at a higher level!
1393 PangoLayout
*layout
= pango_layout_new(m_context
);
1394 pango_layout_set_font_description(layout
, m_fontdesc
);
1396 const wxWX2MBbuf data
= text
.mb_str(wxConvUTF8
);
1397 pango_layout_set_text(layout
, data
, strlen(data
));
1399 PangoLayoutLine
*line
= (PangoLayoutLine
*)pango_layout_get_lines(layout
)->data
;
1400 PangoRectangle rect
;
1401 pango_layout_line_get_extents(line
, NULL
, &rect
);
1402 wxCoord width
= rect
.width
;
1403 wxCoord height
= rect
.height
;
1404 gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout
);
1406 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1407 wxCoord height
= font
->ascent
+ font
->descent
;
1409 if ( m_backgroundMode
== wxSOLID
)
1411 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1412 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1413 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1415 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1416 #endif // GTK+ 2.0/1.x
1418 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1419 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1420 properties (see wxXt implementation) */
1421 if (m_font
.GetUnderlined())
1423 wxCoord ul_y
= y
+ font
->ascent
;
1424 if (font
->descent
> 0) ul_y
++;
1425 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1428 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1429 g_object_unref( G_OBJECT( layout
) );
1432 width
= wxCoord(width
/ m_scaleX
);
1433 height
= wxCoord(height
/ m_scaleY
);
1434 CalcBoundingBox (x
+ width
, y
+ height
);
1435 CalcBoundingBox (x
, y
);
1438 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1442 DrawText(text
, x
, y
);
1446 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1448 if (!m_window
) return;
1450 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1452 wxCHECK_RET( font
, wxT("invalid font") );
1454 // the size of the text
1455 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1456 wxCoord h
= font
->ascent
+ font
->descent
;
1458 // draw the string normally
1461 dc
.SelectObject(src
);
1462 dc
.SetFont(GetFont());
1463 dc
.SetBackground(*wxWHITE_BRUSH
);
1464 dc
.SetBrush(*wxBLACK_BRUSH
);
1466 dc
.DrawText(text
, 0, 0);
1467 dc
.SelectObject(wxNullBitmap
);
1469 // Calculate the size of the rotated bounding box.
1470 double rad
= DegToRad(angle
);
1471 double dx
= cos(rad
),
1474 // the rectngle vertices are counted clockwise with the first one being at
1475 // (0, 0) (or, rather, at (x, y))
1477 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1480 double x3
= x4
+ x2
,
1484 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1485 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1486 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1487 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1489 // prepare to blit-with-rotate the bitmap to the DC
1490 wxImage image
= src
.ConvertToImage();
1492 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1493 *colBack
= m_textBackgroundColour
.GetColor();
1495 bool textColSet
= TRUE
;
1497 unsigned char *data
= image
.GetData();
1499 // paint pixel by pixel
1500 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1502 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1504 // transform source coords to dest coords
1505 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1506 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1507 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1508 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1511 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1512 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1514 // change colour if needed
1515 if ( textPixel
!= textColSet
)
1517 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1520 textColSet
= textPixel
;
1523 // don't use DrawPoint() because it uses the current pen
1524 // colour, and we don't need it here
1525 gdk_draw_point( m_window
, m_textGC
,
1526 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
1531 // it would be better to draw with non underlined font and draw the line
1532 // manually here (it would be more straight...)
1534 if ( m_font
.GetUnderlined() )
1536 gdk_draw_line( m_window
, m_textGC
,
1537 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1538 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1542 // restore the font colour
1543 gdk_gc_set_foreground( m_textGC
, colText
);
1545 // update the bounding box
1546 CalcBoundingBox(x
+ minX
, y
+ minY
);
1547 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1550 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1551 wxCoord
*width
, wxCoord
*height
,
1552 wxCoord
*descent
, wxCoord
*externalLeading
,
1553 wxFont
*theFont
) const
1555 wxFont fontToUse
= m_font
;
1556 if (theFont
) fontToUse
= *theFont
;
1558 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1559 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1560 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1561 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1562 if (externalLeading
) (*externalLeading
) = 0; // ??
1565 wxCoord
wxWindowDC::GetCharWidth() const
1567 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1568 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1570 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1573 wxCoord
wxWindowDC::GetCharHeight() const
1575 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1576 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1578 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1581 void wxWindowDC::Clear()
1583 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1585 if (!m_window
) return;
1587 /* - we either are a memory dc or have a window as the
1588 owner. anything else shouldn't happen.
1589 - we don't use gdk_window_clear() as we don't set
1590 the window's background colour anymore. it is too
1591 much pain to keep the DC's and the window's back-
1592 ground colour in synch. */
1597 m_owner
->GetSize( &width
, &height
);
1598 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1605 GetSize( &width
, &height
);
1606 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1611 void wxWindowDC::SetFont( const wxFont
&font
)
1613 wxCHECK_RET( font
.Ok(), _T("invalid font in wxWindowDC::SetFont") );
1621 void wxWindowDC::SetPen( const wxPen
&pen
)
1623 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1625 if (m_pen
== pen
) return;
1629 if (!m_pen
.Ok()) return;
1631 if (!m_window
) return;
1633 gint width
= m_pen
.GetWidth();
1636 // CMB: if width is non-zero scale it with the dc
1641 // X doesn't allow different width in x and y and so we take
1644 ( fabs((double) XLOG2DEVREL(width
)) +
1645 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1649 static const wxGTKDash dotted
[] = {1, 1};
1650 static const wxGTKDash short_dashed
[] = {2, 2};
1651 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1652 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1654 // We express dash pattern in pen width unit, so we are
1655 // independent of zoom factor and so on...
1657 const wxGTKDash
*req_dash
;
1659 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1660 switch (m_pen
.GetStyle())
1664 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1665 req_nb_dash
= m_pen
.GetDashCount();
1666 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1671 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1678 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1680 req_dash
= wxCoord_dashed
;
1685 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1687 req_dash
= short_dashed
;
1692 // lineStyle = GDK_LINE_DOUBLE_DASH;
1693 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1695 req_dash
= dotted_dashed
;
1700 case wxSTIPPLE_MASK_OPAQUE
:
1705 lineStyle
= GDK_LINE_SOLID
;
1706 req_dash
= (wxGTKDash
*)NULL
;
1712 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1713 if (req_dash
&& req_nb_dash
)
1715 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1718 for (int i
= 0; i
< req_nb_dash
; i
++)
1719 real_req_dash
[i
] = req_dash
[i
] * width
;
1720 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1721 delete[] real_req_dash
;
1725 // No Memory. We use non-scaled dash pattern...
1726 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1731 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1732 switch (m_pen
.GetCap())
1734 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1735 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1742 capStyle
= GDK_CAP_NOT_LAST
;
1746 capStyle
= GDK_CAP_ROUND
;
1752 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1753 switch (m_pen
.GetJoin())
1755 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1756 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1758 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1761 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1763 m_pen
.GetColour().CalcPixel( m_cmap
);
1764 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1767 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1769 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1771 if (m_brush
== brush
) return;
1775 if (!m_brush
.Ok()) return;
1777 if (!m_window
) return;
1779 m_brush
.GetColour().CalcPixel( m_cmap
);
1780 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1782 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1784 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1786 if (m_brush
.GetStipple()->GetPixmap())
1788 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1789 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1793 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1794 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1798 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1800 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1801 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1804 if (IS_HATCH(m_brush
.GetStyle()))
1806 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1807 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1808 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1812 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1814 /* CMB 21/7/98: Added SetBackground. Sets background brush
1815 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1817 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1819 if (m_backgroundBrush
== brush
) return;
1821 m_backgroundBrush
= brush
;
1823 if (!m_backgroundBrush
.Ok()) return;
1825 if (!m_window
) return;
1827 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1828 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1829 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1830 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1831 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1833 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1835 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1837 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1839 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1840 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1844 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1845 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1849 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1851 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1852 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1853 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1857 void wxWindowDC::SetLogicalFunction( int function
)
1859 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1861 if (m_logicalFunction
== function
)
1864 // VZ: shouldn't this be a CHECK?
1868 GdkFunction mode
= GDK_COPY
;
1871 case wxXOR
: mode
= GDK_XOR
; break;
1872 case wxINVERT
: mode
= GDK_INVERT
; break;
1873 #if (GTK_MINOR_VERSION > 0)
1874 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1875 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1876 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1877 case wxSET
: mode
= GDK_SET
; break;
1878 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1879 case wxAND
: mode
= GDK_AND
; break;
1880 case wxOR
: mode
= GDK_OR
; break;
1881 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1882 case wxNAND
: mode
= GDK_NAND
; break;
1883 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1884 case wxCOPY
: mode
= GDK_COPY
; break;
1885 case wxNO_OP
: mode
= GDK_NOOP
; break;
1886 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1888 // unsupported by GTK
1889 case wxNOR
: mode
= GDK_COPY
; break;
1893 wxFAIL_MSG( wxT("unsupported logical function") );
1898 m_logicalFunction
= function
;
1900 gdk_gc_set_function( m_penGC
, mode
);
1901 gdk_gc_set_function( m_brushGC
, mode
);
1903 // to stay compatible with wxMSW, we don't apply ROPs to the text
1904 // operations (i.e. DrawText/DrawRotatedText).
1905 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1906 gdk_gc_set_function( m_textGC
, mode
);
1909 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1911 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1913 // don't set m_textForegroundColour to an invalid colour as we'd crash
1914 // later then (we use m_textForegroundColour.GetColor() without checking
1916 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1919 m_textForegroundColour
= col
;
1923 m_textForegroundColour
.CalcPixel( m_cmap
);
1924 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1928 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1930 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1933 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1936 m_textBackgroundColour
= col
;
1940 m_textBackgroundColour
.CalcPixel( m_cmap
);
1941 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1945 void wxWindowDC::SetBackgroundMode( int mode
)
1947 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1949 m_backgroundMode
= mode
;
1951 if (!m_window
) return;
1953 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1954 // transparent/solid background mode
1956 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1958 gdk_gc_set_fill( m_brushGC
,
1959 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1963 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1965 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1968 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1970 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1972 if (!m_window
) return;
1975 rect
.x
= XLOG2DEV(x
);
1976 rect
.y
= YLOG2DEV(y
);
1977 rect
.width
= XLOG2DEVREL(width
);
1978 rect
.height
= YLOG2DEVREL(height
);
1980 if (!m_currentClippingRegion
.IsNull())
1981 m_currentClippingRegion
.Intersect( rect
);
1983 m_currentClippingRegion
.Union( rect
);
1985 #if USE_PAINT_REGION
1986 if (!m_paintClippingRegion
.IsNull())
1987 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1990 wxCoord xx
, yy
, ww
, hh
;
1991 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1992 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1994 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1995 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
1996 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1997 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2000 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
2002 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2006 DestroyClippingRegion();
2010 if (!m_window
) return;
2012 if (!m_currentClippingRegion
.IsNull())
2013 m_currentClippingRegion
.Intersect( region
);
2015 m_currentClippingRegion
.Union( region
);
2017 #if USE_PAINT_REGION
2018 if (!m_paintClippingRegion
.IsNull())
2019 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2022 wxCoord xx
, yy
, ww
, hh
;
2023 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2024 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2026 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2027 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2028 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2029 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2032 void wxWindowDC::DestroyClippingRegion()
2034 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2036 wxDC::DestroyClippingRegion();
2038 m_currentClippingRegion
.Clear();
2040 #if USE_PAINT_REGION
2041 if (!m_paintClippingRegion
.IsEmpty())
2042 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2045 if (!m_window
) return;
2047 if (m_currentClippingRegion
.IsEmpty())
2049 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2050 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2051 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2052 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2056 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2057 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2058 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2059 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2063 void wxWindowDC::Destroy()
2065 if (m_penGC
) wxFreePoolGC( m_penGC
);
2066 m_penGC
= (GdkGC
*) NULL
;
2067 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2068 m_brushGC
= (GdkGC
*) NULL
;
2069 if (m_textGC
) wxFreePoolGC( m_textGC
);
2070 m_textGC
= (GdkGC
*) NULL
;
2071 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2072 m_bgGC
= (GdkGC
*) NULL
;
2075 void wxWindowDC::ComputeScaleAndOrigin()
2077 /* CMB: copy scale to see if it changes */
2078 double origScaleX
= m_scaleX
;
2079 double origScaleY
= m_scaleY
;
2081 wxDC::ComputeScaleAndOrigin();
2083 /* CMB: if scale has changed call SetPen to recalulate the line width */
2084 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2087 /* this is a bit artificial, but we need to force wxDC to think
2088 the pen has changed */
2095 // Resolution in pixels per logical inch
2096 wxSize
wxWindowDC::GetPPI() const
2098 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2101 int wxWindowDC::GetDepth() const
2103 wxFAIL_MSG(wxT("not implemented"));
2109 //-----------------------------------------------------------------------------
2111 //-----------------------------------------------------------------------------
2113 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2115 wxPaintDC::wxPaintDC( wxWindow
*win
)
2118 #if USE_PAINT_REGION
2119 if (!win
->m_clipPaintRegion
)
2122 m_paintClippingRegion
= win
->GetUpdateRegion();
2123 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2126 m_paintClippingRegion
= win
->GetUpdateRegion();
2127 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2130 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2132 gdk_gc_set_clip_region( m_penGC
, region
);
2133 gdk_gc_set_clip_region( m_brushGC
, region
);
2134 gdk_gc_set_clip_region( m_textGC
, region
);
2135 gdk_gc_set_clip_region( m_bgGC
, region
);
2138 #endif // USE_PAINT_REGION
2141 //-----------------------------------------------------------------------------
2143 //-----------------------------------------------------------------------------
2145 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2147 wxClientDC::wxClientDC( wxWindow
*win
)
2150 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2152 #ifdef __WXUNIVERSAL__
2153 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2154 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2155 wxSize size
= win
->GetClientSize();
2156 SetClippingRegion(wxPoint(0, 0), size
);
2157 #endif // __WXUNIVERSAL__
2160 void wxClientDC::DoGetSize(int *width
, int *height
) const
2162 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2164 m_owner
->GetClientSize( width
, height
);
2167 // ----------------------------------------------------------------------------
2169 // ----------------------------------------------------------------------------
2171 class wxDCModule
: public wxModule
2178 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2181 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2183 bool wxDCModule::OnInit()
2189 void wxDCModule::OnExit()