]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk1/dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/dcclient.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "dcclient.h"
15 #define XCopyPlane XCOPYPLANE
18 #include "wx/dcclient.h"
19 #include "wx/dcmemory.h"
21 #include "wx/module.h"
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 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
405 const wxColour
& col
, int style
);
407 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
,
408 const wxColour
& col
, int style
)
410 return wxDoFloodFill(this, x
, y
, col
, style
);
413 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
415 // Generic (and therefore rather inefficient) method.
416 // Could be improved.
418 wxBitmap
bitmap(1, 1);
419 memdc
.SelectObject(bitmap
);
420 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
421 memdc
.SelectObject(wxNullBitmap
);
423 wxImage image
= bitmap
.ConvertToImage();
424 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
428 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
430 wxCHECK_RET( Ok(), wxT("invalid window dc") );
432 if (m_pen
.GetStyle() != wxTRANSPARENT
)
435 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
437 CalcBoundingBox(x1
, y1
);
438 CalcBoundingBox(x2
, y2
);
442 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
444 wxCHECK_RET( Ok(), wxT("invalid window dc") );
446 if (m_pen
.GetStyle() != wxTRANSPARENT
)
451 wxCoord xx
= XLOG2DEV(x
);
452 wxCoord yy
= YLOG2DEV(y
);
455 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
456 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
461 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
462 wxCoord xc
, wxCoord yc
)
464 wxCHECK_RET( Ok(), wxT("invalid window dc") );
466 wxCoord xx1
= XLOG2DEV(x1
);
467 wxCoord yy1
= YLOG2DEV(y1
);
468 wxCoord xx2
= XLOG2DEV(x2
);
469 wxCoord yy2
= YLOG2DEV(y2
);
470 wxCoord xxc
= XLOG2DEV(xc
);
471 wxCoord yyc
= YLOG2DEV(yc
);
472 double dx
= xx1
- xxc
;
473 double dy
= yy1
- yyc
;
474 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
475 wxCoord r
= (wxCoord
)radius
;
476 double radius1
, radius2
;
478 if (xx1
== xx2
&& yy1
== yy2
)
486 radius1
= radius2
= 0.0;
490 radius1
= (xx1
- xxc
== 0) ?
491 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
492 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
493 radius2
= (xx2
- xxc
== 0) ?
494 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
495 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
497 wxCoord alpha1
= wxCoord(radius1
* 64.0);
498 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
499 while (alpha2
<= 0) alpha2
+= 360*64;
500 while (alpha1
> 360*64) alpha1
-= 360*64;
504 if (m_brush
.GetStyle() != wxTRANSPARENT
)
506 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
508 gdk_gc_set_ts_origin( m_textGC
,
509 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
510 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
511 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
512 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
514 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
516 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
517 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
518 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
520 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
522 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
523 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
524 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
526 if (m_brush
.GetStyle() == wxSTIPPLE
)
528 gdk_gc_set_ts_origin( m_brushGC
,
529 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
530 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
531 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
532 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
536 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
540 if (m_pen
.GetStyle() != wxTRANSPARENT
)
542 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
544 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
545 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
549 CalcBoundingBox (x1
, y1
);
550 CalcBoundingBox (x2
, y2
);
553 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
555 wxCHECK_RET( Ok(), wxT("invalid window dc") );
557 wxCoord xx
= XLOG2DEV(x
);
558 wxCoord yy
= YLOG2DEV(y
);
559 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
560 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
562 // CMB: handle -ve width and/or height
563 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
564 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
568 wxCoord start
= wxCoord(sa
* 64.0);
569 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
571 if (m_brush
.GetStyle() != wxTRANSPARENT
)
573 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
575 gdk_gc_set_ts_origin( m_textGC
,
576 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
577 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
578 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
579 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
581 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
583 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
584 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
585 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
587 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
589 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
590 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
591 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
593 if (m_brush
.GetStyle() == wxSTIPPLE
)
595 gdk_gc_set_ts_origin( m_brushGC
,
596 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
597 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
598 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
599 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
603 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
607 if (m_pen
.GetStyle() != wxTRANSPARENT
)
608 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
611 CalcBoundingBox (x
, y
);
612 CalcBoundingBox (x
+ width
, y
+ height
);
615 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
617 wxCHECK_RET( Ok(), wxT("invalid window dc") );
619 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
620 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
622 CalcBoundingBox (x
, y
);
625 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
627 wxCHECK_RET( Ok(), wxT("invalid window dc") );
629 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
632 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
634 for (int i
= 0; i
< n
-1; i
++)
636 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
637 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
638 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
639 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
642 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
644 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
648 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
650 wxCHECK_RET( Ok(), wxT("invalid window dc") );
654 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
656 for (i
= 0 ; i
< n
; i
++)
658 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
659 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
661 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
666 if (m_brush
.GetStyle() != wxTRANSPARENT
)
668 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
670 gdk_gc_set_ts_origin( m_textGC
,
671 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
672 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
673 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
674 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
676 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
678 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
679 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
680 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
682 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
684 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
685 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
686 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
688 if (m_brush
.GetStyle() == wxSTIPPLE
)
690 gdk_gc_set_ts_origin( m_brushGC
,
691 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
692 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
693 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
694 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
698 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
702 if (m_pen
.GetStyle() != wxTRANSPARENT
)
704 for (i
= 0 ; i
< n
; i
++)
706 gdk_draw_line( m_window
, m_penGC
,
709 gdkpoints
[(i
+1)%n
].x
,
710 gdkpoints
[(i
+1)%n
].y
);
718 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
720 wxCHECK_RET( Ok(), wxT("invalid window dc") );
722 wxCoord xx
= XLOG2DEV(x
);
723 wxCoord yy
= YLOG2DEV(y
);
724 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
725 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
727 // CMB: draw nothing if transformed w or h is 0
728 if (ww
== 0 || hh
== 0) return;
730 // CMB: handle -ve width and/or height
731 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
732 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
736 if (m_brush
.GetStyle() != wxTRANSPARENT
)
738 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
740 gdk_gc_set_ts_origin( m_textGC
,
741 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
742 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
743 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
744 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
746 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
748 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
749 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
750 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
752 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
754 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
755 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
756 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
758 if (m_brush
.GetStyle() == wxSTIPPLE
)
760 gdk_gc_set_ts_origin( m_brushGC
,
761 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
762 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
763 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
764 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
768 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
772 if (m_pen
.GetStyle() != wxTRANSPARENT
)
773 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
776 CalcBoundingBox( x
, y
);
777 CalcBoundingBox( x
+ width
, y
+ height
);
780 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
782 wxCHECK_RET( Ok(), wxT("invalid window dc") );
784 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
786 wxCoord xx
= XLOG2DEV(x
);
787 wxCoord yy
= YLOG2DEV(y
);
788 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
789 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
790 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
792 // CMB: handle -ve width and/or height
793 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
794 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
796 // CMB: if radius is zero use DrawRectangle() instead to avoid
797 // X drawing errors with small radii
800 DrawRectangle( x
, y
, width
, height
);
804 // CMB: draw nothing if transformed w or h is 0
805 if (ww
== 0 || hh
== 0) return;
807 // CMB: adjust size if outline is drawn otherwise the result is
808 // 1 pixel too wide and high
809 if (m_pen
.GetStyle() != wxTRANSPARENT
)
817 // CMB: ensure dd is not larger than rectangle otherwise we
818 // get an hour glass shape
820 if (dd
> ww
) dd
= ww
;
821 if (dd
> hh
) dd
= hh
;
824 if (m_brush
.GetStyle() != wxTRANSPARENT
)
826 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
828 gdk_gc_set_ts_origin( m_textGC
,
829 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
830 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
831 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
832 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
833 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
834 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
835 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
836 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
837 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
839 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
841 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
842 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
843 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
844 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
845 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
846 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
847 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
848 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
850 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
852 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
853 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
854 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
855 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
856 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
857 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
858 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
859 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
861 if (m_brush
.GetStyle() == wxSTIPPLE
)
863 gdk_gc_set_ts_origin( m_brushGC
,
864 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
865 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
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 );
876 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
877 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
878 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
879 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
880 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
881 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
885 if (m_pen
.GetStyle() != wxTRANSPARENT
)
887 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
888 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
889 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
890 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
891 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
892 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
893 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
894 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
898 // this ignores the radius
899 CalcBoundingBox( x
, y
);
900 CalcBoundingBox( x
+ width
, y
+ height
);
903 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
905 wxCHECK_RET( Ok(), wxT("invalid window dc") );
907 wxCoord xx
= XLOG2DEV(x
);
908 wxCoord yy
= YLOG2DEV(y
);
909 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
910 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
912 // CMB: handle -ve width and/or height
913 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
914 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
918 if (m_brush
.GetStyle() != wxTRANSPARENT
)
920 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
922 gdk_gc_set_ts_origin( m_textGC
,
923 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
924 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
925 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
926 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
928 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
930 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
931 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
932 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
934 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
936 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
937 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
938 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
940 if (m_brush
.GetStyle() == wxSTIPPLE
)
942 gdk_gc_set_ts_origin( m_brushGC
,
943 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
944 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
945 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
946 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
950 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
954 if (m_pen
.GetStyle() != wxTRANSPARENT
)
955 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
958 CalcBoundingBox( x
, y
);
959 CalcBoundingBox( x
+ width
, y
+ height
);
962 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
964 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
965 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
968 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
969 wxCoord x
, wxCoord y
,
972 wxCHECK_RET( Ok(), wxT("invalid window dc") );
974 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
976 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
978 /* scale/translate size and position */
979 int xx
= XLOG2DEV(x
);
980 int yy
= YLOG2DEV(y
);
982 int w
= bitmap
.GetWidth();
983 int h
= bitmap
.GetHeight();
985 CalcBoundingBox( x
, y
);
986 CalcBoundingBox( x
+ w
, y
+ h
);
988 if (!m_window
) return;
990 int ww
= XLOG2DEVREL(w
);
991 int hh
= YLOG2DEVREL(h
);
993 /* compare to current clipping region */
994 if (!m_currentClippingRegion
.IsNull())
996 wxRegion
tmp( xx
,yy
,ww
,hh
);
997 tmp
.Intersect( m_currentClippingRegion
);
1002 /* scale bitmap if required */
1003 wxBitmap use_bitmap
;
1004 if ((w
!= ww
) || (h
!= hh
))
1006 wxImage image
= bitmap
.ConvertToImage();
1007 image
.Rescale( ww
, hh
);
1009 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1011 use_bitmap
= wxBitmap(image
);
1015 use_bitmap
= bitmap
;
1018 /* apply mask if any */
1019 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1020 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1022 if (useMask
&& mask
)
1024 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1025 #ifndef __WXGTK20__ // TODO fix crash
1026 if (!m_currentClippingRegion
.IsNull())
1029 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1030 GdkGC
*gc
= gdk_gc_new( new_mask
);
1032 gdk_gc_set_foreground( gc
, &col
);
1033 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1035 gdk_gc_set_background( gc
, &col
);
1037 gdk_gc_set_foreground( gc
, &col
);
1038 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1039 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1040 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1041 gdk_gc_set_stipple( gc
, mask
);
1042 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1049 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1051 gdk_gc_set_clip_mask( m_textGC
, mask
);
1052 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1057 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1059 gdk_gc_set_clip_mask( m_penGC
, mask
);
1060 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1064 gdk_bitmap_unref( new_mask
);
1067 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1068 drawing a mono-bitmap (XBitmap) we use the current text GC */
1070 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1072 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1074 /* remove mask again if any */
1075 if (useMask
&& mask
)
1079 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1080 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1081 if (!m_currentClippingRegion
.IsNull())
1082 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1086 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1087 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1088 if (!m_currentClippingRegion
.IsNull())
1089 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1094 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1095 wxCoord width
, wxCoord height
,
1097 wxCoord xsrc
, wxCoord ysrc
,
1100 wxCoord xsrcMask
, wxCoord ysrcMask
)
1102 /* this is the nth try to get this utterly useless function to
1103 work. it now completely ignores the scaling or translation
1104 of the source dc, but scales correctly on the target dc and
1105 knows about possible mask information in a memory dc. */
1107 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1109 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1111 if (!m_window
) return FALSE
;
1114 // transform the source DC coords to the device ones
1115 xsrc
= source
->XLOG2DEV(xsrc
);
1116 ysrc
= source
->YLOG2DEV(ysrc
);
1119 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1120 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1122 bool use_bitmap_method
= FALSE
;
1123 bool is_mono
= FALSE
;
1125 /* TODO: use the mask origin when drawing transparently */
1126 if (xsrcMask
== -1 && ysrcMask
== -1)
1128 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
1131 if (srcDC
->m_isMemDC
)
1133 if (!memDC
->m_selected
.Ok()) return FALSE
;
1135 /* we use the "XCopyArea" way to copy a memory dc into
1136 y different window if the memory dc BOTH
1137 a) doesn't have any mask or its mask isn't used
1141 if (useMask
&& (memDC
->m_selected
.GetMask()))
1143 /* we HAVE TO use the direct way for memory dcs
1144 that have mask since the XCopyArea doesn't know
1146 use_bitmap_method
= TRUE
;
1148 else if (memDC
->m_selected
.GetDepth() == 1)
1150 /* we HAVE TO use the direct way for memory dcs
1151 that are bitmaps because XCopyArea doesn't cope
1152 with different bit depths */
1154 use_bitmap_method
= TRUE
;
1156 else if ((xsrc
== 0) && (ysrc
== 0) &&
1157 (width
== memDC
->m_selected
.GetWidth()) &&
1158 (height
== memDC
->m_selected
.GetHeight()))
1160 /* we SHOULD use the direct way if all of the bitmap
1161 in the memory dc is copied in which case XCopyArea
1162 wouldn't be able able to boost performace by reducing
1163 the area to be scaled */
1164 use_bitmap_method
= TRUE
;
1168 use_bitmap_method
= FALSE
;
1172 CalcBoundingBox( xdest
, ydest
);
1173 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1175 /* scale/translate size and position */
1176 wxCoord xx
= XLOG2DEV(xdest
);
1177 wxCoord yy
= YLOG2DEV(ydest
);
1179 wxCoord ww
= XLOG2DEVREL(width
);
1180 wxCoord hh
= YLOG2DEVREL(height
);
1182 /* compare to current clipping region */
1183 if (!m_currentClippingRegion
.IsNull())
1185 wxRegion
tmp( xx
,yy
,ww
,hh
);
1186 tmp
.Intersect( m_currentClippingRegion
);
1191 int old_logical_func
= m_logicalFunction
;
1192 SetLogicalFunction( logical_func
);
1194 if (use_bitmap_method
)
1196 /* scale/translate bitmap size */
1197 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1198 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1200 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1201 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1203 /* scale bitmap if required */
1204 wxBitmap use_bitmap
;
1206 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1208 wxImage image
= memDC
->m_selected
.ConvertToImage();
1209 image
= image
.Scale( bm_ww
, bm_hh
);
1212 use_bitmap
= wxBitmap(image
.ConvertToMono(255,255,255), 1);
1214 use_bitmap
= wxBitmap(image
);
1218 use_bitmap
= memDC
->m_selected
;
1221 /* apply mask if any */
1222 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1223 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1225 if (useMask
&& mask
)
1227 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1228 #ifndef __WXGTK20__ // TODO fix crash
1229 if (!m_currentClippingRegion
.IsNull())
1232 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1233 GdkGC
*gc
= gdk_gc_new( new_mask
);
1235 gdk_gc_set_foreground( gc
, &col
);
1236 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1238 gdk_gc_set_background( gc
, &col
);
1240 gdk_gc_set_foreground( gc
, &col
);
1241 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1242 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1243 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1244 gdk_gc_set_stipple( gc
, mask
);
1245 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1252 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1254 gdk_gc_set_clip_mask( m_textGC
, mask
);
1255 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1260 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1262 gdk_gc_set_clip_mask( m_penGC
, mask
);
1263 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1266 gdk_bitmap_unref( new_mask
);
1269 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1270 drawing a mono-bitmap (XBitmap) we use the current text GC */
1273 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1275 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1277 /* remove mask again if any */
1278 if (useMask
&& mask
)
1282 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1283 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1284 if (!m_currentClippingRegion
.IsNull())
1285 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1289 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1290 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1291 if (!m_currentClippingRegion
.IsNull())
1292 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1296 else /* use_bitmap_method */
1298 if ((width
!= ww
) || (height
!= hh
))
1300 /* draw source window into a bitmap as we cannot scale
1301 a window in contrast to a bitmap. this would actually
1302 work with memory dcs as well, but we'd lose the mask
1303 information and waste one step in this process since
1304 a memory already has a bitmap. all this is slightly
1305 inefficient as we could take an XImage directly from
1306 an X window, but we'd then also have to care that
1307 the window is not outside the screen (in which case
1308 we'd get a BadMatch or what not).
1309 Is a double XGetImage and combined XGetPixel and
1310 XPutPixel really faster? I'm not sure. look at wxXt
1311 for a different implementation of the same problem. */
1313 wxBitmap
bitmap( width
, height
);
1315 /* copy including child window contents */
1316 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1317 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1319 xsrc
, ysrc
, width
, height
);
1320 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1323 wxImage image
= bitmap
.ConvertToImage();
1324 image
= image
.Scale( ww
, hh
);
1326 /* convert to bitmap */
1327 bitmap
= wxBitmap(image
);
1329 /* draw scaled bitmap */
1330 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1335 /* No scaling and not a memory dc with a mask either */
1337 /* copy including child window contents */
1338 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1339 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1341 xsrc
, ysrc
, width
, height
);
1342 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1346 SetLogicalFunction( old_logical_func
);
1350 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1352 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1354 if (!m_window
) return;
1356 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1358 wxCHECK_RET( font
, wxT("invalid font") );
1360 #if defined(__WXGTK20__)
1361 wxCHECK_RET( m_context
, wxT("no Pango context") );
1367 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1368 // TODO: the layout engine should be abstracted at a higher level!
1369 PangoLayout
*layout
= pango_layout_new(m_context
);
1370 pango_layout_set_font_description(layout
, m_fontdesc
);
1372 const wxWX2MBbuf data
= text
.mb_str(wxConvUTF8
);
1373 pango_layout_set_text(layout
, data
, strlen(data
));
1375 PangoLayoutLine
*line
= (PangoLayoutLine
*)pango_layout_get_lines(layout
)->data
;
1376 PangoRectangle rect
;
1377 pango_layout_line_get_extents(line
, NULL
, &rect
);
1378 wxCoord width
= rect
.width
;
1379 wxCoord height
= rect
.height
;
1380 gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout
);
1382 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1383 wxCoord height
= font
->ascent
+ font
->descent
;
1385 if ( m_backgroundMode
== wxSOLID
)
1387 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1388 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1389 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1391 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1392 #endif // GTK+ 2.0/1.x
1394 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1395 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1396 properties (see wxXt implementation) */
1397 if (m_font
.GetUnderlined())
1399 wxCoord ul_y
= y
+ font
->ascent
;
1400 if (font
->descent
> 0) ul_y
++;
1401 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1404 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1405 g_object_unref( G_OBJECT( layout
) );
1408 width
= wxCoord(width
/ m_scaleX
);
1409 height
= wxCoord(height
/ m_scaleY
);
1410 CalcBoundingBox (x
+ width
, y
+ height
);
1411 CalcBoundingBox (x
, y
);
1414 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1418 DrawText(text
, x
, y
);
1422 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1424 if (!m_window
) return;
1426 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1428 wxCHECK_RET( font
, wxT("invalid font") );
1430 // the size of the text
1431 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1432 wxCoord h
= font
->ascent
+ font
->descent
;
1434 // draw the string normally
1437 dc
.SelectObject(src
);
1438 dc
.SetFont(GetFont());
1439 dc
.SetBackground(*wxWHITE_BRUSH
);
1440 dc
.SetBrush(*wxBLACK_BRUSH
);
1442 dc
.DrawText(text
, 0, 0);
1443 dc
.SelectObject(wxNullBitmap
);
1445 // Calculate the size of the rotated bounding box.
1446 double rad
= DegToRad(angle
);
1447 double dx
= cos(rad
),
1450 // the rectngle vertices are counted clockwise with the first one being at
1451 // (0, 0) (or, rather, at (x, y))
1453 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1456 double x3
= x4
+ x2
,
1460 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1461 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1462 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1463 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1465 // prepare to blit-with-rotate the bitmap to the DC
1466 wxImage image
= src
.ConvertToImage();
1468 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1469 *colBack
= m_textBackgroundColour
.GetColor();
1471 bool textColSet
= TRUE
;
1473 unsigned char *data
= image
.GetData();
1475 // paint pixel by pixel
1476 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1478 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1480 // transform source coords to dest coords
1481 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1482 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1483 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1484 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1487 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1488 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1490 // change colour if needed
1491 if ( textPixel
!= textColSet
)
1493 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1496 textColSet
= textPixel
;
1499 // don't use DrawPoint() because it uses the current pen
1500 // colour, and we don't need it here
1501 gdk_draw_point( m_window
, m_textGC
,
1502 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
1507 // it would be better to draw with non underlined font and draw the line
1508 // manually here (it would be more straight...)
1510 if ( m_font
.GetUnderlined() )
1512 gdk_draw_line( m_window
, m_textGC
,
1513 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1514 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1518 // restore the font colour
1519 gdk_gc_set_foreground( m_textGC
, colText
);
1521 // update the bounding box
1522 CalcBoundingBox(x
+ minX
, y
+ minY
);
1523 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1526 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1527 wxCoord
*width
, wxCoord
*height
,
1528 wxCoord
*descent
, wxCoord
*externalLeading
,
1529 wxFont
*theFont
) const
1531 wxFont fontToUse
= m_font
;
1532 if (theFont
) fontToUse
= *theFont
;
1534 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1535 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1536 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1537 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1538 if (externalLeading
) (*externalLeading
) = 0; // ??
1541 wxCoord
wxWindowDC::GetCharWidth() const
1543 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1544 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1546 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1549 wxCoord
wxWindowDC::GetCharHeight() const
1551 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1552 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1554 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1557 void wxWindowDC::Clear()
1559 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1561 if (!m_window
) return;
1563 // VZ: the code below results in infinite recursion and crashes when
1564 // dc.Clear() is done from OnPaint() so I disable it for now.
1565 // I don't know what the correct fix is but Clear() surely should not
1566 // reenter OnPaint()!
1568 /* - we either are a memory dc or have a window as the
1569 owner. anything else shouldn't happen.
1570 - we don't use gdk_window_clear() as we don't set
1571 the window's background colour anymore. it is too
1572 much pain to keep the DC's and the window's back-
1573 ground colour in synch. */
1584 GetSize( &width
, &height
);
1585 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1590 GetSize( &width
, &height
);
1591 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1595 void wxWindowDC::SetFont( const wxFont
&font
)
1597 // It is common practice to set the font to wxNullFont, so
1598 // don't consider it to be an error
1599 // wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") );
1607 void wxWindowDC::SetPen( const wxPen
&pen
)
1609 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1611 if (m_pen
== pen
) return;
1615 if (!m_pen
.Ok()) return;
1617 if (!m_window
) return;
1619 gint width
= m_pen
.GetWidth();
1622 // CMB: if width is non-zero scale it with the dc
1627 // X doesn't allow different width in x and y and so we take
1630 ( fabs((double) XLOG2DEVREL(width
)) +
1631 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1635 static const wxGTKDash dotted
[] = {1, 1};
1636 static const wxGTKDash short_dashed
[] = {2, 2};
1637 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1638 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1640 // We express dash pattern in pen width unit, so we are
1641 // independent of zoom factor and so on...
1643 const wxGTKDash
*req_dash
;
1645 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1646 switch (m_pen
.GetStyle())
1650 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1651 req_nb_dash
= m_pen
.GetDashCount();
1652 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1657 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1664 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1666 req_dash
= wxCoord_dashed
;
1671 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1673 req_dash
= short_dashed
;
1678 // lineStyle = GDK_LINE_DOUBLE_DASH;
1679 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1681 req_dash
= dotted_dashed
;
1686 case wxSTIPPLE_MASK_OPAQUE
:
1691 lineStyle
= GDK_LINE_SOLID
;
1692 req_dash
= (wxGTKDash
*)NULL
;
1698 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1699 if (req_dash
&& req_nb_dash
)
1701 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1704 for (int i
= 0; i
< req_nb_dash
; i
++)
1705 real_req_dash
[i
] = req_dash
[i
] * width
;
1706 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1707 delete[] real_req_dash
;
1711 // No Memory. We use non-scaled dash pattern...
1712 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1717 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1718 switch (m_pen
.GetCap())
1720 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1721 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1728 capStyle
= GDK_CAP_NOT_LAST
;
1732 capStyle
= GDK_CAP_ROUND
;
1738 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1739 switch (m_pen
.GetJoin())
1741 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1742 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1744 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1747 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1749 m_pen
.GetColour().CalcPixel( m_cmap
);
1750 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1753 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1755 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1757 if (m_brush
== brush
) return;
1761 if (!m_brush
.Ok()) return;
1763 if (!m_window
) return;
1765 m_brush
.GetColour().CalcPixel( m_cmap
);
1766 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1768 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1770 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1772 if (m_brush
.GetStipple()->GetPixmap())
1774 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1775 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1779 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1780 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1784 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1786 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1787 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1790 if (IS_HATCH(m_brush
.GetStyle()))
1792 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1793 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1794 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1798 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1800 /* CMB 21/7/98: Added SetBackground. Sets background brush
1801 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1803 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1805 if (m_backgroundBrush
== brush
) return;
1807 m_backgroundBrush
= brush
;
1809 if (!m_backgroundBrush
.Ok()) return;
1811 if (!m_window
) return;
1813 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1814 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1815 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1816 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1817 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1819 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1821 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1823 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1825 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1826 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1830 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1831 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1835 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1837 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1838 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1839 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1843 void wxWindowDC::SetLogicalFunction( int function
)
1845 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1847 if (m_logicalFunction
== function
)
1850 // VZ: shouldn't this be a CHECK?
1854 GdkFunction mode
= GDK_COPY
;
1857 case wxXOR
: mode
= GDK_XOR
; break;
1858 case wxINVERT
: mode
= GDK_INVERT
; break;
1859 #if (GTK_MINOR_VERSION > 0)
1860 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1861 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1862 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1863 case wxSET
: mode
= GDK_SET
; break;
1864 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1865 case wxAND
: mode
= GDK_AND
; break;
1866 case wxOR
: mode
= GDK_OR
; break;
1867 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1868 case wxNAND
: mode
= GDK_NAND
; break;
1869 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1870 case wxCOPY
: mode
= GDK_COPY
; break;
1871 case wxNO_OP
: mode
= GDK_NOOP
; break;
1872 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1874 // unsupported by GTK
1875 case wxNOR
: mode
= GDK_COPY
; break;
1879 wxFAIL_MSG( wxT("unsupported logical function") );
1884 m_logicalFunction
= function
;
1886 gdk_gc_set_function( m_penGC
, mode
);
1887 gdk_gc_set_function( m_brushGC
, mode
);
1889 // to stay compatible with wxMSW, we don't apply ROPs to the text
1890 // operations (i.e. DrawText/DrawRotatedText).
1891 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1892 gdk_gc_set_function( m_textGC
, mode
);
1895 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1897 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1899 // don't set m_textForegroundColour to an invalid colour as we'd crash
1900 // later then (we use m_textForegroundColour.GetColor() without checking
1902 if ( !col
.Ok() || (m_textForegroundColour
== col
) )
1905 m_textForegroundColour
= col
;
1909 m_textForegroundColour
.CalcPixel( m_cmap
);
1910 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1914 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1916 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1919 if ( !col
.Ok() || (m_textBackgroundColour
== col
) )
1922 m_textBackgroundColour
= col
;
1926 m_textBackgroundColour
.CalcPixel( m_cmap
);
1927 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1931 void wxWindowDC::SetBackgroundMode( int mode
)
1933 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1935 m_backgroundMode
= mode
;
1937 if (!m_window
) return;
1939 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1940 // transparent/solid background mode
1942 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1944 gdk_gc_set_fill( m_brushGC
,
1945 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1949 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1951 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1954 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1956 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1958 if (!m_window
) return;
1961 rect
.x
= XLOG2DEV(x
);
1962 rect
.y
= YLOG2DEV(y
);
1963 rect
.width
= XLOG2DEVREL(width
);
1964 rect
.height
= YLOG2DEVREL(height
);
1966 if (!m_currentClippingRegion
.IsNull())
1967 m_currentClippingRegion
.Intersect( rect
);
1969 m_currentClippingRegion
.Union( rect
);
1971 #if USE_PAINT_REGION
1972 if (!m_paintClippingRegion
.IsNull())
1973 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1976 wxCoord xx
, yy
, ww
, hh
;
1977 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1978 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1980 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1981 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
1982 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1983 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
1986 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1988 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1992 DestroyClippingRegion();
1996 if (!m_window
) return;
1998 if (!m_currentClippingRegion
.IsNull())
1999 m_currentClippingRegion
.Intersect( region
);
2001 m_currentClippingRegion
.Union( region
);
2003 #if USE_PAINT_REGION
2004 if (!m_paintClippingRegion
.IsNull())
2005 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
2008 wxCoord xx
, yy
, ww
, hh
;
2009 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
2010 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
2012 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2013 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2014 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2015 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2018 void wxWindowDC::DestroyClippingRegion()
2020 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2022 wxDC::DestroyClippingRegion();
2024 m_currentClippingRegion
.Clear();
2026 #if USE_PAINT_REGION
2027 if (!m_paintClippingRegion
.IsEmpty())
2028 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2031 if (!m_window
) return;
2033 if (m_currentClippingRegion
.IsEmpty())
2035 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2036 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2037 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2038 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2042 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2043 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2044 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2045 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2049 void wxWindowDC::Destroy()
2051 if (m_penGC
) wxFreePoolGC( m_penGC
);
2052 m_penGC
= (GdkGC
*) NULL
;
2053 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2054 m_brushGC
= (GdkGC
*) NULL
;
2055 if (m_textGC
) wxFreePoolGC( m_textGC
);
2056 m_textGC
= (GdkGC
*) NULL
;
2057 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2058 m_bgGC
= (GdkGC
*) NULL
;
2061 void wxWindowDC::ComputeScaleAndOrigin()
2063 /* CMB: copy scale to see if it changes */
2064 double origScaleX
= m_scaleX
;
2065 double origScaleY
= m_scaleY
;
2067 wxDC::ComputeScaleAndOrigin();
2069 /* CMB: if scale has changed call SetPen to recalulate the line width */
2070 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2073 /* this is a bit artificial, but we need to force wxDC to think
2074 the pen has changed */
2081 // Resolution in pixels per logical inch
2082 wxSize
wxWindowDC::GetPPI() const
2084 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2087 int wxWindowDC::GetDepth() const
2089 wxFAIL_MSG(wxT("not implemented"));
2095 //-----------------------------------------------------------------------------
2097 //-----------------------------------------------------------------------------
2099 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2101 wxPaintDC::wxPaintDC( wxWindow
*win
)
2104 #if USE_PAINT_REGION
2105 if (!win
->m_clipPaintRegion
)
2108 m_paintClippingRegion
= win
->GetUpdateRegion();
2109 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2112 m_paintClippingRegion
= win
->GetUpdateRegion();
2113 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2116 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2118 gdk_gc_set_clip_region( m_penGC
, region
);
2119 gdk_gc_set_clip_region( m_brushGC
, region
);
2120 gdk_gc_set_clip_region( m_textGC
, region
);
2121 gdk_gc_set_clip_region( m_bgGC
, region
);
2124 #endif // USE_PAINT_REGION
2127 //-----------------------------------------------------------------------------
2129 //-----------------------------------------------------------------------------
2131 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2133 wxClientDC::wxClientDC( wxWindow
*win
)
2136 wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") );
2138 #ifdef __WXUNIVERSAL__
2139 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2140 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2141 wxSize size
= win
->GetClientSize();
2142 SetClippingRegion(wxPoint(0, 0), size
);
2143 #endif // __WXUNIVERSAL__
2146 void wxClientDC::DoGetSize(int *width
, int *height
) const
2148 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
2150 m_owner
->GetClientSize( width
, height
);
2153 // ----------------------------------------------------------------------------
2155 // ----------------------------------------------------------------------------
2157 class wxDCModule
: public wxModule
2164 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2167 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2169 bool wxDCModule::OnInit()
2175 void wxDCModule::OnExit()