]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/dcclient.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "dcclient.h"
15 #define XCopyPlane XCOPYPLANE
18 #include "wx/dcclient.h"
19 #include "wx/dcmemory.h"
21 #include "wx/module.h"
23 #include "wx/gtk/win_gtk.h"
25 #include <math.h> // for floating-point functions
29 #include <gdk/gdkprivate.h>
32 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
36 #define USE_PAINT_REGION 1
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
50 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
51 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
54 static GdkPixmap
*hatches
[num_hatches
];
55 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
57 extern GtkWidget
*wxGetRootWindow();
59 //-----------------------------------------------------------------------------
61 //-----------------------------------------------------------------------------
63 const double RAD2DEG
= 180.0 / M_PI
;
65 // ----------------------------------------------------------------------------
67 // ----------------------------------------------------------------------------
69 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
70 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
72 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
74 //-----------------------------------------------------------------------------
75 // temporary implementation of the missing GDK function
76 //-----------------------------------------------------------------------------
78 #include "gdk/gdkprivate.h"
80 void gdk_wx_draw_bitmap(GdkDrawable
*drawable
,
90 gint src_width
, src_height
;
92 GdkWindowPrivate
*drawable_private
;
93 GdkWindowPrivate
*src_private
;
94 GdkGCPrivate
*gc_private
;
97 g_return_if_fail (drawable
!= NULL
);
98 g_return_if_fail (src
!= NULL
);
99 g_return_if_fail (gc
!= NULL
);
102 if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
))
105 gdk_drawable_get_size(src
, &src_width
, &src_height
);
107 drawable_private
= (GdkWindowPrivate
*) drawable
;
108 src_private
= (GdkWindowPrivate
*) src
;
109 if (drawable_private
->destroyed
|| src_private
->destroyed
)
112 src_width
= src_private
->width
;
113 src_height
= src_private
->height
;
115 gc_private
= (GdkGCPrivate
*) gc
;
118 if (width
== -1) width
= src_width
;
119 if (height
== -1) height
= src_height
;
122 XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
),
124 GDK_WINDOW_XID(drawable
),
131 XCopyPlane( drawable_private
->xdisplay
,
132 src_private
->xwindow
,
133 drawable_private
->xwindow
,
142 //-----------------------------------------------------------------------------
143 // Implement Pool of Graphic contexts. Creating them takes too much time.
144 //-----------------------------------------------------------------------------
146 #define GC_POOL_SIZE 200
172 static wxGC wxGCPool
[GC_POOL_SIZE
];
174 static void wxInitGCPool()
176 memset( wxGCPool
, 0, GC_POOL_SIZE
*sizeof(wxGC
) );
179 static void wxCleanUpGCPool()
181 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
183 if (wxGCPool
[i
].m_gc
)
184 gdk_gc_unref( wxGCPool
[i
].m_gc
);
188 static GdkGC
* wxGetPoolGC( GdkWindow
*window
, wxPoolGCType type
)
190 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
192 if (!wxGCPool
[i
].m_gc
)
194 wxGCPool
[i
].m_gc
= gdk_gc_new( window
);
195 gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE
);
196 wxGCPool
[i
].m_type
= type
;
197 wxGCPool
[i
].m_used
= FALSE
;
199 if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type
== type
))
201 wxGCPool
[i
].m_used
= TRUE
;
202 return wxGCPool
[i
].m_gc
;
206 wxFAIL_MSG( wxT("No GC available") );
208 return (GdkGC
*) NULL
;
211 static void wxFreePoolGC( GdkGC
*gc
)
213 for (int i
= 0; i
< GC_POOL_SIZE
; i
++)
215 if (wxGCPool
[i
].m_gc
== gc
)
217 wxGCPool
[i
].m_used
= FALSE
;
222 wxFAIL_MSG( wxT("Wrong GC") );
225 //-----------------------------------------------------------------------------
227 //-----------------------------------------------------------------------------
229 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
231 wxWindowDC::wxWindowDC()
233 m_penGC
= (GdkGC
*) NULL
;
234 m_brushGC
= (GdkGC
*) NULL
;
235 m_textGC
= (GdkGC
*) NULL
;
236 m_bgGC
= (GdkGC
*) NULL
;
237 m_cmap
= (GdkColormap
*) NULL
;
239 m_isScreenDC
= FALSE
;
240 m_owner
= (wxWindow
*)NULL
;
242 m_context
= (PangoContext
*)NULL
;
243 m_fontdesc
= (PangoFontDescription
*)NULL
;
247 wxWindowDC::wxWindowDC( wxWindow
*window
)
249 m_penGC
= (GdkGC
*) NULL
;
250 m_brushGC
= (GdkGC
*) NULL
;
251 m_textGC
= (GdkGC
*) NULL
;
252 m_bgGC
= (GdkGC
*) NULL
;
253 m_cmap
= (GdkColormap
*) NULL
;
254 m_owner
= (wxWindow
*)NULL
;
256 m_isScreenDC
= FALSE
;
257 m_font
= window
->GetFont();
259 wxASSERT_MSG( window
, wxT("DC needs a window") );
261 GtkWidget
*widget
= window
->m_wxwindow
;
263 // some controls don't have m_wxwindow - like wxStaticBox, but the user
264 // code should still be able to create wxClientDCs for them, so we will
265 // use the parent window here then
268 window
= window
->GetParent();
269 widget
= window
->m_wxwindow
;
272 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
275 m_context
= gtk_widget_get_pango_context( widget
);
276 m_fontdesc
= widget
->style
->font_desc
;
279 GtkPizza
*pizza
= GTK_PIZZA( widget
);
280 m_window
= pizza
->bin_window
;
285 /* don't report problems */
291 m_cmap
= gtk_widget_get_colormap( widget
? widget
: window
->m_widget
);
295 /* this must be done after SetUpDC, bacause SetUpDC calls the
296 repective SetBrush, SetPen, SetBackground etc functions
297 to set up the DC. SetBackground call m_owner->SetBackground
298 and this might not be desired as the standard dc background
299 is white whereas a window might assume gray to be the
300 standard (as e.g. wxStatusBar) */
305 wxWindowDC::~wxWindowDC()
310 void wxWindowDC::SetUpDC()
314 wxASSERT_MSG( !m_penGC
, wxT("GCs already created") );
318 m_penGC
= wxGetPoolGC( m_window
, wxPEN_SCREEN
);
319 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN
);
320 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_SCREEN
);
321 m_bgGC
= wxGetPoolGC( m_window
, wxBG_SCREEN
);
324 if (m_isMemDC
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1))
326 m_penGC
= wxGetPoolGC( m_window
, wxPEN_MONO
);
327 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_MONO
);
328 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_MONO
);
329 m_bgGC
= wxGetPoolGC( m_window
, wxBG_MONO
);
333 m_penGC
= wxGetPoolGC( m_window
, wxPEN_COLOUR
);
334 m_brushGC
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR
);
335 m_textGC
= wxGetPoolGC( m_window
, wxTEXT_COLOUR
);
336 m_bgGC
= wxGetPoolGC( m_window
, wxBG_COLOUR
);
339 /* background colour */
340 m_backgroundBrush
= *wxWHITE_BRUSH
;
341 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
342 GdkColor
*bg_col
= m_backgroundBrush
.GetColour().GetColor();
345 m_textForegroundColour
.CalcPixel( m_cmap
);
346 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
348 m_textBackgroundColour
.CalcPixel( m_cmap
);
349 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
351 gdk_gc_set_fill( m_textGC
, GDK_SOLID
);
354 m_pen
.GetColour().CalcPixel( m_cmap
);
355 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
356 gdk_gc_set_background( m_penGC
, bg_col
);
358 gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND
);
361 m_brush
.GetColour().CalcPixel( m_cmap
);
362 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
363 gdk_gc_set_background( m_brushGC
, bg_col
);
365 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
368 gdk_gc_set_background( m_bgGC
, bg_col
);
369 gdk_gc_set_foreground( m_bgGC
, bg_col
);
371 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
374 gdk_gc_set_function( m_textGC
, GDK_COPY
);
375 gdk_gc_set_function( m_brushGC
, GDK_COPY
);
376 gdk_gc_set_function( m_penGC
, GDK_COPY
);
379 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
380 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
381 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
382 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
386 hatch_bitmap
= hatches
;
387 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
388 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
389 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
390 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
391 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
392 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
396 void wxWindowDC::DoGetSize( int* width
, int* height
) const
398 wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") );
400 m_owner
->GetSize(width
, height
);
403 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
404 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
406 wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") );
409 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour
*col
) const
411 // Generic (and therefore rather inefficient) method.
412 // Could be improved.
414 wxBitmap
bitmap(1, 1);
415 memdc
.SelectObject(bitmap
);
416 memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
);
417 memdc
.SelectObject(wxNullBitmap
);
419 wxImage
image(bitmap
);
420 col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0));
424 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
426 wxCHECK_RET( Ok(), wxT("invalid window dc") );
428 if (m_pen
.GetStyle() != wxTRANSPARENT
)
431 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
433 CalcBoundingBox(x1
, y1
);
434 CalcBoundingBox(x2
, y2
);
438 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
440 wxCHECK_RET( Ok(), wxT("invalid window dc") );
442 if (m_pen
.GetStyle() != wxTRANSPARENT
)
447 wxCoord xx
= XLOG2DEV(x
);
448 wxCoord yy
= YLOG2DEV(y
);
451 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
452 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
457 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
458 wxCoord xc
, wxCoord yc
)
460 wxCHECK_RET( Ok(), wxT("invalid window dc") );
462 wxCoord xx1
= XLOG2DEV(x1
);
463 wxCoord yy1
= YLOG2DEV(y1
);
464 wxCoord xx2
= XLOG2DEV(x2
);
465 wxCoord yy2
= YLOG2DEV(y2
);
466 wxCoord xxc
= XLOG2DEV(xc
);
467 wxCoord yyc
= YLOG2DEV(yc
);
468 double dx
= xx1
- xxc
;
469 double dy
= yy1
- yyc
;
470 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
471 wxCoord r
= (wxCoord
)radius
;
472 double radius1
, radius2
;
474 if (xx1
== xx2
&& yy1
== yy2
)
482 radius1
= radius2
= 0.0;
486 radius1
= (xx1
- xxc
== 0) ?
487 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
488 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
489 radius2
= (xx2
- xxc
== 0) ?
490 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
491 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
493 wxCoord alpha1
= wxCoord(radius1
* 64.0);
494 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
495 while (alpha2
<= 0) alpha2
+= 360*64;
496 while (alpha1
> 360*64) alpha1
-= 360*64;
500 if (m_brush
.GetStyle() != wxTRANSPARENT
)
502 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
504 gdk_gc_set_ts_origin( m_textGC
,
505 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
506 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
507 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
508 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
510 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
512 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
513 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
514 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
516 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
518 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
519 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
520 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
522 if (m_brush
.GetStyle() == wxSTIPPLE
)
524 gdk_gc_set_ts_origin( m_brushGC
,
525 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
526 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
527 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
528 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
532 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
536 if (m_pen
.GetStyle() != wxTRANSPARENT
)
538 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
540 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc
);
541 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2
);
545 CalcBoundingBox (x1
, y1
);
546 CalcBoundingBox (x2
, y2
);
549 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
551 wxCHECK_RET( Ok(), wxT("invalid window dc") );
553 wxCoord xx
= XLOG2DEV(x
);
554 wxCoord yy
= YLOG2DEV(y
);
555 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
556 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
558 // CMB: handle -ve width and/or height
559 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
560 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
564 wxCoord start
= wxCoord(sa
* 64.0);
565 wxCoord end
= wxCoord((ea
-sa
) * 64.0);
567 if (m_brush
.GetStyle() != wxTRANSPARENT
)
569 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
571 gdk_gc_set_ts_origin( m_textGC
,
572 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
573 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
574 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
575 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
577 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
579 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
580 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
581 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
583 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
585 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
586 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
587 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
589 if (m_brush
.GetStyle() == wxSTIPPLE
)
591 gdk_gc_set_ts_origin( m_brushGC
,
592 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
593 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
594 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
595 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
599 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
603 if (m_pen
.GetStyle() != wxTRANSPARENT
)
604 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
607 CalcBoundingBox (x
, y
);
608 CalcBoundingBox (x
+ width
, y
+ height
);
611 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
613 wxCHECK_RET( Ok(), wxT("invalid window dc") );
615 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
616 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
618 CalcBoundingBox (x
, y
);
621 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
623 wxCHECK_RET( Ok(), wxT("invalid window dc") );
625 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
628 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
630 for (int i
= 0; i
< n
-1; i
++)
632 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
633 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
634 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
635 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
638 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
640 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
644 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
646 wxCHECK_RET( Ok(), wxT("invalid window dc") );
650 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
652 for (i
= 0 ; i
< n
; i
++)
654 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
655 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
657 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
662 if (m_brush
.GetStyle() != wxTRANSPARENT
)
664 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
666 gdk_gc_set_ts_origin( m_textGC
,
667 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
668 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
669 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
670 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
672 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
674 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
675 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
676 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
678 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
680 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
681 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
682 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
684 if (m_brush
.GetStyle() == wxSTIPPLE
)
686 gdk_gc_set_ts_origin( m_brushGC
,
687 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
688 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
689 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
690 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
694 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
698 if (m_pen
.GetStyle() != wxTRANSPARENT
)
700 for (i
= 0 ; i
< n
; i
++)
702 gdk_draw_line( m_window
, m_penGC
,
705 gdkpoints
[(i
+1)%n
].x
,
706 gdkpoints
[(i
+1)%n
].y
);
714 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
716 wxCHECK_RET( Ok(), wxT("invalid window dc") );
718 wxCoord xx
= XLOG2DEV(x
);
719 wxCoord yy
= YLOG2DEV(y
);
720 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
721 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
723 // CMB: draw nothing if transformed w or h is 0
724 if (ww
== 0 || hh
== 0) return;
726 // CMB: handle -ve width and/or height
727 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
728 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
732 if (m_brush
.GetStyle() != wxTRANSPARENT
)
734 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
736 gdk_gc_set_ts_origin( m_textGC
,
737 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
738 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
739 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
740 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
742 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
744 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
745 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
746 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
748 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
750 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
751 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
752 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
754 if (m_brush
.GetStyle() == wxSTIPPLE
)
756 gdk_gc_set_ts_origin( m_brushGC
,
757 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
758 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
759 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
760 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
764 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
768 if (m_pen
.GetStyle() != wxTRANSPARENT
)
769 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
772 CalcBoundingBox( x
, y
);
773 CalcBoundingBox( x
+ width
, y
+ height
);
776 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
778 wxCHECK_RET( Ok(), wxT("invalid window dc") );
780 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
782 wxCoord xx
= XLOG2DEV(x
);
783 wxCoord yy
= YLOG2DEV(y
);
784 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
785 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
786 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
788 // CMB: handle -ve width and/or height
789 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
790 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
792 // CMB: if radius is zero use DrawRectangle() instead to avoid
793 // X drawing errors with small radii
796 DrawRectangle( x
, y
, width
, height
);
800 // CMB: draw nothing if transformed w or h is 0
801 if (ww
== 0 || hh
== 0) return;
803 // CMB: adjust size if outline is drawn otherwise the result is
804 // 1 pixel too wide and high
805 if (m_pen
.GetStyle() != wxTRANSPARENT
)
813 // CMB: ensure dd is not larger than rectangle otherwise we
814 // get an hour glass shape
816 if (dd
> ww
) dd
= ww
;
817 if (dd
> hh
) dd
= hh
;
820 if (m_brush
.GetStyle() != wxTRANSPARENT
)
822 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
824 gdk_gc_set_ts_origin( m_textGC
,
825 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
826 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
827 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
828 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
829 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
830 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
831 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
832 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
833 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
835 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
837 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
838 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
839 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
840 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
841 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
842 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
843 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
844 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
846 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
848 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
849 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
850 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
851 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
852 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
853 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
854 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
855 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
857 if (m_brush
.GetStyle() == wxSTIPPLE
)
859 gdk_gc_set_ts_origin( m_brushGC
,
860 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
861 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
862 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
863 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
864 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
865 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
866 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
867 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
868 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
872 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
873 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
874 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
875 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
876 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
877 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
881 if (m_pen
.GetStyle() != wxTRANSPARENT
)
883 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy
);
884 gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
885 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr
);
886 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr
);
887 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
888 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
889 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
890 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
894 // this ignores the radius
895 CalcBoundingBox( x
, y
);
896 CalcBoundingBox( x
+ width
, y
+ height
);
899 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
901 wxCHECK_RET( Ok(), wxT("invalid window dc") );
903 wxCoord xx
= XLOG2DEV(x
);
904 wxCoord yy
= YLOG2DEV(y
);
905 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
906 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
908 // CMB: handle -ve width and/or height
909 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
910 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
914 if (m_brush
.GetStyle() != wxTRANSPARENT
)
916 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
918 gdk_gc_set_ts_origin( m_textGC
,
919 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
920 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
921 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
922 gdk_gc_set_ts_origin( m_textGC
, 0, 0 );
924 if (IS_15_PIX_HATCH(m_brush
.GetStyle()))
926 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 15, m_deviceOriginY
% 15 );
927 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
928 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
930 if (IS_16_PIX_HATCH(m_brush
.GetStyle()))
932 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX
% 16, m_deviceOriginY
% 16 );
933 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
934 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
936 if (m_brush
.GetStyle() == wxSTIPPLE
)
938 gdk_gc_set_ts_origin( m_brushGC
,
939 m_deviceOriginX
% m_brush
.GetStipple()->GetWidth(),
940 m_deviceOriginY
% m_brush
.GetStipple()->GetHeight() );
941 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
942 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 );
946 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
950 if (m_pen
.GetStyle() != wxTRANSPARENT
)
951 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
954 CalcBoundingBox( x
, y
);
955 CalcBoundingBox( x
+ width
, y
+ height
);
958 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
960 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
961 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
964 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
965 wxCoord x
, wxCoord y
,
968 wxCHECK_RET( Ok(), wxT("invalid window dc") );
970 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
972 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
974 /* scale/translate size and position */
975 int xx
= XLOG2DEV(x
);
976 int yy
= YLOG2DEV(y
);
978 int w
= bitmap
.GetWidth();
979 int h
= bitmap
.GetHeight();
981 CalcBoundingBox( x
, y
);
982 CalcBoundingBox( x
+ w
, y
+ h
);
984 if (!m_window
) return;
986 int ww
= XLOG2DEVREL(w
);
987 int hh
= YLOG2DEVREL(h
);
989 /* compare to current clipping region */
990 if (!m_currentClippingRegion
.IsNull())
992 wxRegion
tmp( xx
,yy
,ww
,hh
);
993 tmp
.Intersect( m_currentClippingRegion
);
998 /* scale bitmap if required */
1000 if ((w
!= ww
) || (h
!= hh
))
1002 wxImage
image( bitmap
);
1003 image
.Rescale( ww
, hh
);
1005 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
1007 use_bitmap
= image
.ConvertToBitmap();
1011 use_bitmap
= bitmap
;
1014 /* apply mask if any */
1015 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1016 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1018 if (useMask
&& mask
)
1020 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1021 if (!m_currentClippingRegion
.IsNull())
1024 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 );
1025 GdkGC
*gc
= gdk_gc_new( new_mask
);
1027 gdk_gc_set_foreground( gc
, &col
);
1028 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1030 gdk_gc_set_background( gc
, &col
);
1032 gdk_gc_set_foreground( gc
, &col
);
1033 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1034 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1035 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1036 gdk_gc_set_stipple( gc
, mask
);
1037 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh
);
1044 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1046 gdk_gc_set_clip_mask( m_textGC
, mask
);
1047 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1052 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1054 gdk_gc_set_clip_mask( m_penGC
, mask
);
1055 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1058 gdk_bitmap_unref( new_mask
);
1061 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1062 drawing a mono-bitmap (XBitmap) we use the current text GC */
1064 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
1066 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1068 /* remove mask again if any */
1069 if (useMask
&& mask
)
1073 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1074 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1075 if (!m_currentClippingRegion
.IsNull())
1076 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1080 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1081 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1082 if (!m_currentClippingRegion
.IsNull())
1083 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1088 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
,
1089 wxCoord width
, wxCoord height
,
1091 wxCoord xsrc
, wxCoord ysrc
,
1095 /* this is the nth try to get this utterly useless function to
1096 work. it now completely ignores the scaling or translation
1097 of the source dc, but scales correctly on the target dc and
1098 knows about possible mask information in a memory dc. */
1100 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
1102 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
1104 if (!m_window
) return FALSE
;
1107 // transform the source DC coords to the device ones
1108 xsrc
= XLOG2DEV(xsrc
);
1109 ysrc
= YLOG2DEV(ysrc
);
1112 wxClientDC
*srcDC
= (wxClientDC
*)source
;
1113 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
1115 bool use_bitmap_method
= FALSE
;
1116 bool is_mono
= FALSE
;
1118 if (srcDC
->m_isMemDC
)
1120 if (!memDC
->m_selected
.Ok()) return FALSE
;
1122 /* we use the "XCopyArea" way to copy a memory dc into
1123 y different window if the memory dc BOTH
1124 a) doesn't have any mask or its mask isn't used
1128 if (useMask
&& (memDC
->m_selected
.GetMask()))
1130 /* we HAVE TO use the direct way for memory dcs
1131 that have mask since the XCopyArea doesn't know
1133 use_bitmap_method
= TRUE
;
1135 else if (memDC
->m_selected
.GetDepth() == 1)
1137 /* we HAVE TO use the direct way for memory dcs
1138 that are bitmaps because XCopyArea doesn't cope
1139 with different bit depths */
1141 use_bitmap_method
= TRUE
;
1143 else if ((xsrc
== 0) && (ysrc
== 0) &&
1144 (width
== memDC
->m_selected
.GetWidth()) &&
1145 (height
== memDC
->m_selected
.GetHeight()))
1147 /* we SHOULD use the direct way if all of the bitmap
1148 in the memory dc is copied in which case XCopyArea
1149 wouldn't be able able to boost performace by reducing
1150 the area to be scaled */
1151 use_bitmap_method
= TRUE
;
1155 use_bitmap_method
= FALSE
;
1159 CalcBoundingBox( xdest
, ydest
);
1160 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
1162 /* scale/translate size and position */
1163 wxCoord xx
= XLOG2DEV(xdest
);
1164 wxCoord yy
= YLOG2DEV(ydest
);
1166 wxCoord ww
= XLOG2DEVREL(width
);
1167 wxCoord hh
= YLOG2DEVREL(height
);
1169 /* compare to current clipping region */
1170 if (!m_currentClippingRegion
.IsNull())
1172 wxRegion
tmp( xx
,yy
,ww
,hh
);
1173 tmp
.Intersect( m_currentClippingRegion
);
1178 int old_logical_func
= m_logicalFunction
;
1179 SetLogicalFunction( logical_func
);
1181 if (use_bitmap_method
)
1183 /* scale/translate bitmap size */
1184 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
1185 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
1187 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
1188 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
1190 /* scale bitmap if required */
1191 wxBitmap use_bitmap
;
1193 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
1195 wxImage
image( memDC
->m_selected
);
1196 image
= image
.Scale( bm_ww
, bm_hh
);
1199 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
1201 use_bitmap
= image
.ConvertToBitmap();
1205 use_bitmap
= memDC
->m_selected
;
1208 /* apply mask if any */
1209 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
1210 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
1212 if (useMask
&& mask
)
1214 GdkBitmap
*new_mask
= (GdkBitmap
*) NULL
;
1215 if (!m_currentClippingRegion
.IsNull())
1218 new_mask
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 );
1219 GdkGC
*gc
= gdk_gc_new( new_mask
);
1221 gdk_gc_set_foreground( gc
, &col
);
1222 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1224 gdk_gc_set_background( gc
, &col
);
1226 gdk_gc_set_foreground( gc
, &col
);
1227 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() );
1228 gdk_gc_set_clip_origin( gc
, -xx
, -yy
);
1229 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED
);
1230 gdk_gc_set_stipple( gc
, mask
);
1231 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh
);
1238 gdk_gc_set_clip_mask( m_textGC
, new_mask
);
1240 gdk_gc_set_clip_mask( m_textGC
, mask
);
1241 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
1246 gdk_gc_set_clip_mask( m_penGC
, new_mask
);
1248 gdk_gc_set_clip_mask( m_penGC
, mask
);
1249 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
1252 gdk_bitmap_unref( new_mask
);
1255 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1256 drawing a mono-bitmap (XBitmap) we use the current text GC */
1259 gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1261 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
1263 /* remove mask again if any */
1264 if (useMask
&& mask
)
1268 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
1269 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
1270 if (!m_currentClippingRegion
.IsNull())
1271 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1275 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
1276 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
1277 if (!m_currentClippingRegion
.IsNull())
1278 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1282 else /* use_bitmap_method */
1284 if ((width
!= ww
) || (height
!= hh
))
1286 /* draw source window into a bitmap as we cannot scale
1287 a window in contrast to a bitmap. this would actually
1288 work with memory dcs as well, but we'd lose the mask
1289 information and waste one step in this process since
1290 a memory already has a bitmap. all this is slightly
1291 inefficient as we could take an XImage directly from
1292 an X window, but we'd then also have to care that
1293 the window is not outside the screen (in which case
1294 we'd get a BadMatch or what not).
1295 Is a double XGetImage and combined XGetPixel and
1296 XPutPixel really faster? I'm not sure. look at wxXt
1297 for a different implementation of the same problem. */
1299 wxBitmap
bitmap( width
, height
);
1301 /* copy including child window contents */
1302 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1303 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
1305 xsrc
, ysrc
, width
, height
);
1306 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1309 wxImage
image( bitmap
);
1310 image
= image
.Scale( ww
, hh
);
1312 /* convert to bitmap */
1313 bitmap
= image
.ConvertToBitmap();
1315 /* draw scaled bitmap */
1316 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
1321 /* No scaling and not a memory dc with a mask either */
1323 /* copy including child window contents */
1324 gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS
);
1325 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
1327 xsrc
, ysrc
, width
, height
);
1328 gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN
);
1332 SetLogicalFunction( old_logical_func
);
1336 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
1338 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1340 if (!m_window
) return;
1342 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1344 wxCHECK_RET( font
, wxT("invalid font") );
1346 #if defined(__WXGTK20__)
1347 wxCHECK_RET( m_context
, wxT("no Pango context") );
1353 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1354 /* FIXME: the layout engine should probably be abstracted at a higher level in wxDC... */
1355 PangoLayout
*layout
= pango_layout_new(m_context
);
1356 pango_layout_set_font_description(layout
, m_fontdesc
);
1358 wxWX2MBbuf data
= text
.mb_str(wxConvUTF8
);
1359 pango_layout_set_text(layout
, data
, strlen(data
));
1361 PangoLayoutLine
*line
= (PangoLayoutLine
*)pango_layout_get_lines(layout
)->data
;
1362 PangoRectangle rect
;
1363 pango_layout_line_get_extents(line
, NULL
, &rect
);
1364 wxCoord width
= rect
.width
;
1365 wxCoord height
= rect
.height
;
1366 gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout
);
1368 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
1369 wxCoord height
= font
->ascent
+ font
->descent
;
1370 /* CMB 21/5/98: draw text background if mode is wxSOLID */
1371 if (m_backgroundMode
== wxSOLID
)
1373 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
1374 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
1375 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1377 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
1380 /* CMB 17/7/98: simple underline: ignores scaling and underlying
1381 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
1382 properties (see wxXt implementation) */
1383 if (m_font
.GetUnderlined())
1385 wxCoord ul_y
= y
+ font
->ascent
;
1386 if (font
->descent
> 0) ul_y
++;
1387 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
1390 #if defined(__WXGTK20__) && wxUSE_WCHAR_T
1391 g_object_unref( G_OBJECT( layout
) );
1394 width
= wxCoord(width
/ m_scaleX
);
1395 height
= wxCoord(height
/ m_scaleY
);
1396 CalcBoundingBox (x
+ width
, y
+ height
);
1397 CalcBoundingBox (x
, y
);
1400 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
1404 DrawText(text
, x
, y
);
1408 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1410 if (!m_window
) return;
1412 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1414 wxCHECK_RET( font
, wxT("invalid font") );
1416 // the size of the text
1417 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
1418 wxCoord h
= font
->ascent
+ font
->descent
;
1420 // draw the string normally
1423 dc
.SelectObject(src
);
1424 dc
.SetFont(GetFont());
1425 dc
.SetBackground(*wxWHITE_BRUSH
);
1426 dc
.SetBrush(*wxBLACK_BRUSH
);
1428 dc
.DrawText(text
, 0, 0);
1429 dc
.SetFont(wxNullFont
);
1430 dc
.SelectObject(wxNullBitmap
);
1432 // Calculate the size of the rotated bounding box.
1433 double rad
= DegToRad(angle
);
1434 double dx
= cos(rad
),
1437 // the rectngle vertices are counted clockwise with the first one being at
1438 // (0, 0) (or, rather, at (x, y))
1440 y2
= -w
*dy
; // y axis points to the bottom, hence minus
1443 double x3
= x4
+ x2
,
1447 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
1448 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
1449 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
1450 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
1452 // prepare to blit-with-rotate the bitmap to the DC
1455 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
1456 *colBack
= m_textBackgroundColour
.GetColor();
1458 bool textColSet
= TRUE
;
1460 unsigned char *data
= image
.GetData();
1462 // paint pixel by pixel
1463 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
1465 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
1467 // transform source coords to dest coords
1468 double r
= sqrt((double)srcX
*srcX
+ srcY
*srcY
);
1469 double angleOrig
= atan2((double)srcY
, (double)srcX
) - rad
;
1470 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
1471 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
1474 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
1475 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
1477 // change colour if needed
1478 if ( textPixel
!= textColSet
)
1480 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
1483 textColSet
= textPixel
;
1486 // don't use DrawPoint() because it uses the current pen
1487 // colour, and we don't need it here
1488 gdk_draw_point( m_window
, m_textGC
,
1489 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
1494 // it would be better to draw with non underlined font and draw the line
1495 // manually here (it would be more straight...)
1497 if ( m_font
.GetUnderlined() )
1499 gdk_draw_line( m_window
, m_textGC
,
1500 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
1501 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
1505 // restore the font colour
1506 gdk_gc_set_foreground( m_textGC
, colText
);
1508 // update the bounding box
1509 CalcBoundingBox(x
+ minX
, y
+ minY
);
1510 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
1513 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
1514 wxCoord
*width
, wxCoord
*height
,
1515 wxCoord
*descent
, wxCoord
*externalLeading
,
1516 wxFont
*theFont
) const
1518 wxFont fontToUse
= m_font
;
1519 if (theFont
) fontToUse
= *theFont
;
1521 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
1522 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
1523 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1524 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
1525 if (externalLeading
) (*externalLeading
) = 0; // ??
1528 wxCoord
wxWindowDC::GetCharWidth() const
1530 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1531 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1533 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
1536 wxCoord
wxWindowDC::GetCharHeight() const
1538 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
1539 wxCHECK_MSG( font
, -1, wxT("invalid font") );
1541 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
1544 void wxWindowDC::Clear()
1546 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1548 if (!m_window
) return;
1550 /* - we either are a memory dc or have a window as the
1551 owner. anything else shouldn't happen.
1552 - we don't use gdk_window_clear() as we don't set
1553 the window's background colour anymore. it is too
1554 much pain to keep the DC's and the window's back-
1555 ground colour in synch. */
1560 m_owner
->GetSize( &width
, &height
);
1561 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1568 GetSize( &width
, &height
);
1569 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1574 void wxWindowDC::SetFont( const wxFont
&font
)
1582 void wxWindowDC::SetPen( const wxPen
&pen
)
1584 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1586 if (m_pen
== pen
) return;
1590 if (!m_pen
.Ok()) return;
1592 if (!m_window
) return;
1594 gint width
= m_pen
.GetWidth();
1597 // CMB: if width is non-zero scale it with the dc
1602 // X doesn't allow different width in x and y and so we take
1605 ( fabs((double) XLOG2DEVREL(width
)) +
1606 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1610 static const wxGTKDash dotted
[] = {1, 1};
1611 static const wxGTKDash short_dashed
[] = {2, 2};
1612 static const wxGTKDash wxCoord_dashed
[] = {2, 4};
1613 static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3};
1615 // We express dash pattern in pen width unit, so we are
1616 // independent of zoom factor and so on...
1618 const wxGTKDash
*req_dash
;
1620 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1621 switch (m_pen
.GetStyle())
1625 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1626 req_nb_dash
= m_pen
.GetDashCount();
1627 req_dash
= (wxGTKDash
*)m_pen
.GetDash();
1632 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1639 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1641 req_dash
= wxCoord_dashed
;
1646 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1648 req_dash
= short_dashed
;
1653 // lineStyle = GDK_LINE_DOUBLE_DASH;
1654 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1656 req_dash
= dotted_dashed
;
1661 case wxSTIPPLE_MASK_OPAQUE
:
1666 lineStyle
= GDK_LINE_SOLID
;
1667 req_dash
= (wxGTKDash
*)NULL
;
1673 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
1674 if (req_dash
&& req_nb_dash
)
1676 wxGTKDash
*real_req_dash
= new wxGTKDash
[req_nb_dash
];
1679 for (int i
= 0; i
< req_nb_dash
; i
++)
1680 real_req_dash
[i
] = req_dash
[i
] * width
;
1681 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1682 delete[] real_req_dash
;
1686 // No Memory. We use non-scaled dash pattern...
1687 gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash
);
1692 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1693 switch (m_pen
.GetCap())
1695 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1696 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1703 capStyle
= GDK_CAP_NOT_LAST
;
1707 capStyle
= GDK_CAP_ROUND
;
1713 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1714 switch (m_pen
.GetJoin())
1716 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1717 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1719 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1722 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1724 m_pen
.GetColour().CalcPixel( m_cmap
);
1725 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1728 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1730 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1732 if (m_brush
== brush
) return;
1736 if (!m_brush
.Ok()) return;
1738 if (!m_window
) return;
1740 m_brush
.GetColour().CalcPixel( m_cmap
);
1741 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1743 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1745 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1747 if (m_brush
.GetStipple()->GetPixmap())
1749 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1750 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1754 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1755 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1759 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1761 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1762 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1765 if (IS_HATCH(m_brush
.GetStyle()))
1767 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1768 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1769 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1773 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1775 /* CMB 21/7/98: Added SetBackground. Sets background brush
1776 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1778 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1780 if (m_backgroundBrush
== brush
) return;
1782 m_backgroundBrush
= brush
;
1784 if (!m_backgroundBrush
.Ok()) return;
1786 if (!m_window
) return;
1788 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1789 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1790 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1791 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1792 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1794 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1796 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1798 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1800 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1801 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1805 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1806 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1810 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1812 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1813 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1814 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1818 void wxWindowDC::SetLogicalFunction( int function
)
1820 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1822 if (m_logicalFunction
== function
)
1825 // VZ: shouldn't this be a CHECK?
1829 GdkFunction mode
= GDK_COPY
;
1832 case wxXOR
: mode
= GDK_XOR
; break;
1833 case wxINVERT
: mode
= GDK_INVERT
; break;
1834 #if (GTK_MINOR_VERSION > 0)
1835 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1836 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1837 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1838 case wxSET
: mode
= GDK_SET
; break;
1839 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1840 case wxAND
: mode
= GDK_AND
; break;
1841 case wxOR
: mode
= GDK_OR
; break;
1842 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1843 case wxNAND
: mode
= GDK_NAND
; break;
1844 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1845 case wxCOPY
: mode
= GDK_COPY
; break;
1846 case wxNO_OP
: mode
= GDK_NOOP
; break;
1847 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1849 // unsupported by GTK
1850 case wxNOR
: mode
= GDK_COPY
; break;
1854 wxFAIL_MSG( wxT("unsupported logical function") );
1859 m_logicalFunction
= function
;
1861 gdk_gc_set_function( m_penGC
, mode
);
1862 gdk_gc_set_function( m_brushGC
, mode
);
1864 // to stay compatible with wxMSW, we don't apply ROPs to the text
1865 // operations (i.e. DrawText/DrawRotatedText).
1866 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1867 gdk_gc_set_function( m_textGC
, mode
);
1870 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1872 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1874 if (m_textForegroundColour
== col
) return;
1876 m_textForegroundColour
= col
;
1877 if (!m_textForegroundColour
.Ok()) return;
1879 if (!m_window
) return;
1881 m_textForegroundColour
.CalcPixel( m_cmap
);
1882 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1885 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1887 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1889 if (m_textBackgroundColour
== col
) return;
1891 m_textBackgroundColour
= col
;
1892 if (!m_textBackgroundColour
.Ok()) return;
1894 if (!m_window
) return;
1896 m_textBackgroundColour
.CalcPixel( m_cmap
);
1897 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1900 void wxWindowDC::SetBackgroundMode( int mode
)
1902 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1904 m_backgroundMode
= mode
;
1906 if (!m_window
) return;
1908 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1909 // transparent/solid background mode
1911 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1913 gdk_gc_set_fill( m_brushGC
,
1914 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1918 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1920 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1923 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1925 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1927 if (!m_window
) return;
1930 rect
.x
= XLOG2DEV(x
);
1931 rect
.y
= YLOG2DEV(y
);
1932 rect
.width
= XLOG2DEVREL(width
);
1933 rect
.height
= YLOG2DEVREL(height
);
1935 if (!m_currentClippingRegion
.IsNull())
1936 m_currentClippingRegion
.Intersect( rect
);
1938 m_currentClippingRegion
.Union( rect
);
1940 #if USE_PAINT_REGION
1941 if (!m_paintClippingRegion
.IsNull())
1942 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1945 wxCoord xx
, yy
, ww
, hh
;
1946 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1947 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1949 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1950 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
1951 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1952 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
1955 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1957 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1961 DestroyClippingRegion();
1965 if (!m_window
) return;
1967 if (!m_currentClippingRegion
.IsNull())
1968 m_currentClippingRegion
.Intersect( region
);
1970 m_currentClippingRegion
.Union( region
);
1972 #if USE_PAINT_REGION
1973 if (!m_paintClippingRegion
.IsNull())
1974 m_currentClippingRegion
.Intersect( m_paintClippingRegion
);
1977 wxCoord xx
, yy
, ww
, hh
;
1978 m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh
);
1979 wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh
);
1981 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
1982 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
1983 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
1984 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
1987 void wxWindowDC::DestroyClippingRegion()
1989 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1991 wxDC::DestroyClippingRegion();
1993 m_currentClippingRegion
.Clear();
1995 #if USE_PAINT_REGION
1996 if (!m_paintClippingRegion
.IsEmpty())
1997 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2000 if (!m_window
) return;
2002 if (m_currentClippingRegion
.IsEmpty())
2004 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
2005 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
2006 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
2007 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
2011 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() );
2012 gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() );
2013 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() );
2014 gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() );
2018 void wxWindowDC::Destroy()
2020 if (m_penGC
) wxFreePoolGC( m_penGC
);
2021 m_penGC
= (GdkGC
*) NULL
;
2022 if (m_brushGC
) wxFreePoolGC( m_brushGC
);
2023 m_brushGC
= (GdkGC
*) NULL
;
2024 if (m_textGC
) wxFreePoolGC( m_textGC
);
2025 m_textGC
= (GdkGC
*) NULL
;
2026 if (m_bgGC
) wxFreePoolGC( m_bgGC
);
2027 m_bgGC
= (GdkGC
*) NULL
;
2030 void wxWindowDC::ComputeScaleAndOrigin()
2032 /* CMB: copy scale to see if it changes */
2033 double origScaleX
= m_scaleX
;
2034 double origScaleY
= m_scaleY
;
2036 wxDC::ComputeScaleAndOrigin();
2038 /* CMB: if scale has changed call SetPen to recalulate the line width */
2039 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
2042 /* this is a bit artificial, but we need to force wxDC to think
2043 the pen has changed */
2050 // Resolution in pixels per logical inch
2051 wxSize
wxWindowDC::GetPPI() const
2053 return wxSize( (int) (m_mm_to_pix_x
* 25.4 + 0.5), (int) (m_mm_to_pix_y
* 25.4 + 0.5));
2056 int wxWindowDC::GetDepth() const
2058 wxFAIL_MSG(wxT("not implemented"));
2064 //-----------------------------------------------------------------------------
2066 //-----------------------------------------------------------------------------
2068 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
)
2070 wxPaintDC::wxPaintDC( wxWindow
*win
)
2073 #if USE_PAINT_REGION
2074 if (!win
->m_clipPaintRegion
)
2077 m_paintClippingRegion
= win
->GetUpdateRegion();
2078 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2081 m_paintClippingRegion
= win
->GetUpdateRegion();
2082 GdkRegion
*region
= m_paintClippingRegion
.GetRegion();
2085 m_currentClippingRegion
.Union( m_paintClippingRegion
);
2087 gdk_gc_set_clip_region( m_penGC
, region
);
2088 gdk_gc_set_clip_region( m_brushGC
, region
);
2089 gdk_gc_set_clip_region( m_textGC
, region
);
2090 gdk_gc_set_clip_region( m_bgGC
, region
);
2093 #endif // USE_PAINT_REGION
2096 //-----------------------------------------------------------------------------
2098 //-----------------------------------------------------------------------------
2100 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
2102 wxClientDC::wxClientDC( wxWindow
*win
)
2105 #ifdef __WXUNIVERSAL__
2106 wxPoint ptOrigin
= win
->GetClientAreaOrigin();
2107 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
2108 wxSize size
= win
->GetClientSize();
2109 SetClippingRegion(wxPoint(0, 0), size
);
2110 #endif // __WXUNIVERSAL__
2113 // ----------------------------------------------------------------------------
2115 // ----------------------------------------------------------------------------
2117 class wxDCModule
: public wxModule
2124 DECLARE_DYNAMIC_CLASS(wxDCModule
)
2127 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
)
2129 bool wxDCModule::OnInit()
2135 void wxDCModule::OnExit()