1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "dcclient.h"
14 #include "wx/dcclient.h"
15 #include "wx/dcmemory.h"
17 #include "wx/gtk/win_gtk.h"
19 #include <math.h> // for floating-point functions
23 //-----------------------------------------------------------------------------
25 //-----------------------------------------------------------------------------
35 static GdkPixmap
*hatches
[num_hatches
];
36 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 const double RAD2DEG
= 180.0 / M_PI
;
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 static inline double dmax(double a
, double b
) { return a
> b
? a
: b
; }
49 static inline double dmin(double a
, double b
) { return a
< b
? a
: b
; }
51 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
53 //-----------------------------------------------------------------------------
54 // temporary implementation of the missing GDK function
55 //-----------------------------------------------------------------------------
57 #include "gdk/gdkprivate.h"
59 void gdk_draw_bitmap (GdkDrawable
*drawable
,
69 GdkWindowPrivate
*drawable_private
;
70 GdkWindowPrivate
*src_private
;
71 GdkGCPrivate
*gc_private
;
73 g_return_if_fail (drawable
!= NULL
);
74 g_return_if_fail (src
!= NULL
);
75 g_return_if_fail (gc
!= NULL
);
77 drawable_private
= (GdkWindowPrivate
*) drawable
;
78 src_private
= (GdkWindowPrivate
*) src
;
79 if (drawable_private
->destroyed
|| src_private
->destroyed
)
82 gc_private
= (GdkGCPrivate
*) gc
;
84 if (width
== -1) width
= src_private
->width
;
85 if (height
== -1) height
= src_private
->height
;
87 XCopyPlane( drawable_private
->xdisplay
,
89 drawable_private
->xwindow
,
97 //-----------------------------------------------------------------------------
99 //-----------------------------------------------------------------------------
101 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
103 wxWindowDC::wxWindowDC()
105 m_penGC
= (GdkGC
*) NULL
;
106 m_brushGC
= (GdkGC
*) NULL
;
107 m_textGC
= (GdkGC
*) NULL
;
108 m_bgGC
= (GdkGC
*) NULL
;
109 m_cmap
= (GdkColormap
*) NULL
;
111 m_owner
= (wxWindow
*)NULL
;
114 wxWindowDC::wxWindowDC( wxWindow
*window
)
116 m_penGC
= (GdkGC
*) NULL
;
117 m_brushGC
= (GdkGC
*) NULL
;
118 m_textGC
= (GdkGC
*) NULL
;
119 m_bgGC
= (GdkGC
*) NULL
;
120 m_cmap
= (GdkColormap
*) NULL
;
121 m_owner
= (wxWindow
*)NULL
;
123 m_font
= window
->GetFont();
125 wxASSERT_MSG( window
, wxT("DC needs a window") );
127 GtkWidget
*widget
= window
->m_wxwindow
;
129 wxASSERT_MSG( widget
, wxT("DC needs a widget") );
131 GtkPizza
*pizza
= GTK_PIZZA( widget
);
132 m_window
= pizza
->bin_window
;
137 /* don't report problems */
143 if (window
->m_wxwindow
)
144 m_cmap
= gtk_widget_get_colormap( window
->m_wxwindow
);
146 m_cmap
= gtk_widget_get_colormap( window
->m_widget
);
150 /* this must be done after SetUpDC, bacause SetUpDC calls the
151 repective SetBrush, SetPen, SetBackground etc functions
152 to set up the DC. SetBackground call m_owner->SetBackground
153 and this might not be desired as the standard dc background
154 is white whereas a window might assume gray to be the
155 standard (as e.g. wxStatusBar) */
160 wxWindowDC::~wxWindowDC()
165 void wxWindowDC::DoFloodFill( wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
166 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
168 wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") );
171 bool wxWindowDC::DoGetPixel( wxCoord
WXUNUSED(x1
), wxCoord
WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
173 wxFAIL_MSG( wxT("wxWindowDC::DoGetPixel not implemented") );
177 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
179 wxCHECK_RET( Ok(), wxT("invalid window dc") );
181 if (m_pen
.GetStyle() != wxTRANSPARENT
)
184 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
186 CalcBoundingBox(x1
, y1
);
187 CalcBoundingBox(x2
, y2
);
191 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y
)
193 wxCHECK_RET( Ok(), wxT("invalid window dc") );
195 if (m_pen
.GetStyle() != wxTRANSPARENT
)
200 wxCoord xx
= XLOG2DEV(x
);
201 wxCoord yy
= YLOG2DEV(y
);
204 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
205 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
210 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
,
211 wxCoord xc
, wxCoord yc
)
213 wxCHECK_RET( Ok(), wxT("invalid window dc") );
215 wxCoord xx1
= XLOG2DEV(x1
);
216 wxCoord yy1
= YLOG2DEV(y1
);
217 wxCoord xx2
= XLOG2DEV(x2
);
218 wxCoord yy2
= YLOG2DEV(y2
);
219 wxCoord xxc
= XLOG2DEV(xc
);
220 wxCoord yyc
= YLOG2DEV(yc
);
221 double dx
= xx1
- xxc
;
222 double dy
= yy1
- yyc
;
223 double radius
= sqrt((double)(dx
*dx
+dy
*dy
));
224 wxCoord r
= (wxCoord
)radius
;
225 double radius1
, radius2
;
227 if (xx1
== xx2
&& yy1
== yy2
)
235 radius1
= radius2
= 0.0;
239 radius1
= (xx1
- xxc
== 0) ?
240 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
241 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
242 radius2
= (xx2
- xxc
== 0) ?
243 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
244 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
246 wxCoord alpha1
= wxCoord(radius1
* 64.0);
247 wxCoord alpha2
= wxCoord((radius2
- radius1
) * 64.0);
248 while (alpha2
<= 0) alpha2
+= 360*64;
249 while (alpha1
> 360*64) alpha1
-= 360*64;
253 if (m_brush
.GetStyle() != wxTRANSPARENT
)
254 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
256 if (m_pen
.GetStyle() != wxTRANSPARENT
)
257 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
260 CalcBoundingBox (x1
, y1
);
261 CalcBoundingBox (x2
, y2
);
264 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea
)
266 wxCHECK_RET( Ok(), wxT("invalid window dc") );
268 wxCoord xx
= XLOG2DEV(x
);
269 wxCoord yy
= YLOG2DEV(y
);
270 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
271 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
273 // CMB: handle -ve width and/or height
274 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
275 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
279 wxCoord start
= wxCoord(sa
* 64.0);
280 wxCoord end
= wxCoord(ea
* 64.0);
282 if (m_brush
.GetStyle() != wxTRANSPARENT
)
283 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
285 if (m_pen
.GetStyle() != wxTRANSPARENT
)
286 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
289 CalcBoundingBox (x
, y
);
290 CalcBoundingBox (x
+ width
, y
+ height
);
293 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y
)
295 wxCHECK_RET( Ok(), wxT("invalid window dc") );
297 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
298 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
300 CalcBoundingBox (x
, y
);
303 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
305 wxCHECK_RET( Ok(), wxT("invalid window dc") );
307 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
310 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
312 for (int i
= 0; i
< n
-1; i
++)
314 wxCoord x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
315 wxCoord x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
316 wxCoord y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
317 wxCoord y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
320 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
322 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
326 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) )
328 wxCHECK_RET( Ok(), wxT("invalid window dc") );
332 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
334 for (i
= 0 ; i
< n
; i
++)
336 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
337 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
339 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
344 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
345 gdk_draw_polygon (m_window
, m_textGC
, TRUE
, gdkpoints
, n
);
348 if ((m_brush
.GetStyle() != wxTRANSPARENT
))
349 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
355 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
357 for (i
= 0 ; i
< n
; i
++)
359 gdk_draw_line( m_window
, m_penGC
,
362 gdkpoints
[(i
+1)%n
].x
,
363 gdkpoints
[(i
+1)%n
].y
);
370 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
372 wxCHECK_RET( Ok(), wxT("invalid window dc") );
374 wxCoord xx
= XLOG2DEV(x
);
375 wxCoord yy
= YLOG2DEV(y
);
376 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
377 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
379 // CMB: draw nothing if transformed w or h is 0
380 if (ww
== 0 || hh
== 0) return;
382 // CMB: handle -ve width and/or height
383 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
384 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
388 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
390 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
);
391 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
395 if (m_brush
.GetStyle() != wxTRANSPARENT
)
396 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
398 if (m_pen
.GetStyle() != wxTRANSPARENT
)
399 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
403 CalcBoundingBox( x
, y
);
404 CalcBoundingBox( x
+ width
, y
+ height
);
407 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
409 wxCHECK_RET( Ok(), wxT("invalid window dc") );
411 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
413 wxCoord xx
= XLOG2DEV(x
);
414 wxCoord yy
= YLOG2DEV(y
);
415 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
416 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
417 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
419 // CMB: handle -ve width and/or height
420 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
421 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
423 // CMB: if radius is zero use DrawRectangle() instead to avoid
424 // X drawing errors with small radii
427 DrawRectangle( x
, y
, width
, height
);
431 // CMB: draw nothing if transformed w or h is 0
432 if (ww
== 0 || hh
== 0) return;
434 // CMB: adjust size if outline is drawn otherwise the result is
435 // 1 pixel too wide and high
436 if (m_pen
.GetStyle() != wxTRANSPARENT
)
444 // CMB: ensure dd is not larger than rectangle otherwise we
445 // get an hour glass shape
447 if (dd
> ww
) dd
= ww
;
448 if (dd
> hh
) dd
= hh
;
451 if (m_brush
.GetStyle() != wxTRANSPARENT
)
453 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
454 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
455 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
456 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
457 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
458 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
461 if (m_pen
.GetStyle() != wxTRANSPARENT
)
463 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
464 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
465 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
466 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
467 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
468 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
469 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
470 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
474 // this ignores the radius
475 CalcBoundingBox( x
, y
);
476 CalcBoundingBox( x
+ width
, y
+ height
);
479 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
481 wxCHECK_RET( Ok(), wxT("invalid window dc") );
483 wxCoord xx
= XLOG2DEV(x
);
484 wxCoord yy
= YLOG2DEV(y
);
485 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
486 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
488 // CMB: handle -ve width and/or height
489 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
490 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
494 if (m_brush
.GetStyle() != wxTRANSPARENT
)
495 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
497 if (m_pen
.GetStyle() != wxTRANSPARENT
)
498 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
501 CalcBoundingBox( x
- width
, y
- height
);
502 CalcBoundingBox( x
+ width
, y
+ height
);
505 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
507 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
508 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
511 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
512 wxCoord x
, wxCoord y
,
515 wxCHECK_RET( Ok(), wxT("invalid window dc") );
517 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
519 bool is_mono
= (bitmap
.GetBitmap() != NULL
);
521 /* scale/translate size and position */
523 int xx
= XLOG2DEV(x
);
524 int yy
= YLOG2DEV(y
);
526 int w
= bitmap
.GetWidth();
527 int h
= bitmap
.GetHeight();
529 CalcBoundingBox( x
, y
);
530 CalcBoundingBox( x
+ w
, y
+ h
);
532 if (!m_window
) return;
534 int ww
= XLOG2DEVREL(w
);
535 int hh
= YLOG2DEVREL(h
);
537 /* scale bitmap if required */
541 if ((w
!= ww
) || (h
!= hh
))
543 wxImage
image( bitmap
);
544 image
.Rescale( ww
, hh
);
546 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
548 use_bitmap
= image
.ConvertToBitmap();
555 /* apply mask if any */
557 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
558 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
564 gdk_gc_set_clip_mask( m_textGC
, mask
);
565 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
569 gdk_gc_set_clip_mask( m_penGC
, mask
);
570 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
574 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
575 drawing a mono-bitmap (XBitmap) we use the current text GC */
577 gdk_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 );
579 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
581 /* remove mask again if any */
587 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
588 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
592 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
593 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
598 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
599 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
600 int logical_func
, bool useMask
)
602 /* this is the nth try to get this utterly useless function to
603 work. it now completely ignores the scaling or translation
604 of the source dc, but scales correctly on the target dc and
605 knows about possible mask information in a memory dc. */
607 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
609 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
611 if (!m_window
) return FALSE
;
613 wxClientDC
*srcDC
= (wxClientDC
*)source
;
614 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
616 bool use_bitmap_method
= FALSE
;
617 bool is_mono
= FALSE
;
619 if (srcDC
->m_isMemDC
)
621 if (!memDC
->m_selected
.Ok()) return FALSE
;
623 /* we use the "XCopyArea" way to copy a memory dc into
624 y different window if the memory dc BOTH
625 a) doesn't have any mask or its mask isn't used
629 if (useMask
&& (memDC
->m_selected
.GetMask()))
631 /* we HAVE TO use the direct way for memory dcs
632 that have mask since the XCopyArea doesn't know
634 use_bitmap_method
= TRUE
;
636 else if (memDC
->m_selected
.GetDepth() == 1)
638 /* we HAVE TO use the direct way for memory dcs
639 that are bitmaps because XCopyArea doesn't cope
640 with different bit depths */
642 use_bitmap_method
= TRUE
;
644 else if ((xsrc
== 0) && (ysrc
== 0) &&
645 (width
== memDC
->m_selected
.GetWidth()) &&
646 (height
== memDC
->m_selected
.GetHeight()))
648 /* we SHOULD use the direct way if all of the bitmap
649 in the memory dc is copied in which case XCopyArea
650 wouldn't be able able to boost performace by reducing
651 the area to be scaled */
652 use_bitmap_method
= TRUE
;
656 use_bitmap_method
= FALSE
;
660 CalcBoundingBox( xdest
, ydest
);
661 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
663 int old_logical_func
= m_logicalFunction
;
664 SetLogicalFunction( logical_func
);
666 if (use_bitmap_method
)
668 /* scale/translate bitmap size */
670 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
671 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
673 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
674 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
676 /* scale bitmap if required */
680 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
682 wxImage
image( memDC
->m_selected
);
683 image
= image
.Scale( bm_ww
, bm_hh
);
686 use_bitmap
= image
.ConvertToMonoBitmap(255,255,255);
688 use_bitmap
= image
.ConvertToBitmap();
692 use_bitmap
= memDC
->m_selected
;
695 /* scale/translate size and position */
697 wxCoord xx
= XLOG2DEV(xdest
);
698 wxCoord yy
= YLOG2DEV(ydest
);
700 wxCoord ww
= XLOG2DEVREL(width
);
701 wxCoord hh
= YLOG2DEVREL(height
);
703 /* apply mask if any */
705 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
706 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
712 gdk_gc_set_clip_mask( m_textGC
, mask
);
713 gdk_gc_set_clip_origin( m_textGC
, xx
, yy
);
717 gdk_gc_set_clip_mask( m_penGC
, mask
);
718 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
722 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
723 drawing a mono-bitmap (XBitmap) we use the current text GC */
725 gdk_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
727 gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh
);
729 /* remove mask again if any */
735 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap
*) NULL
);
736 gdk_gc_set_clip_origin( m_textGC
, 0, 0 );
740 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
741 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
745 else /* use_bitmap_method */
747 /* scale/translate size and position */
749 wxCoord xx
= XLOG2DEV(xdest
);
750 wxCoord yy
= YLOG2DEV(ydest
);
752 wxCoord ww
= XLOG2DEVREL(width
);
753 wxCoord hh
= YLOG2DEVREL(height
);
755 if ((width
!= ww
) || (height
!= hh
))
757 /* draw source window into a bitmap as we cannot scale
758 a window in contrast to a bitmap. this would actually
759 work with memory dcs as well, but we'd lose the mask
760 information and waste one step in this process since
761 a memory already has a bitmap. all this is slightly
762 inefficient as we could take an XImage directly from
763 an X window, but we'd then also have to care that
764 the window is not outside the screen (in which case
765 we'd get a BadMatch or what not).
766 Is a double XGetImage and combined XGetPixel and
767 XPutPixel really faster? I'm not sure. look at wxXt
768 for a different implementation of the same problem. */
770 wxBitmap
bitmap( width
, height
);
771 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
773 xsrc
, ysrc
, width
, height
);
777 wxImage
image( bitmap
);
778 image
= image
.Scale( ww
, hh
);
780 /* convert to bitmap */
782 bitmap
= image
.ConvertToBitmap();
784 /* draw scaled bitmap */
786 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
791 /* no scaling and not a memory dc with a mask either */
793 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
795 xsrc
, ysrc
, width
, height
);
799 SetLogicalFunction( old_logical_func
);
803 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
805 wxCHECK_RET( Ok(), wxT("invalid window dc") );
807 if (!m_window
) return;
809 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
811 wxCHECK_RET( font
, wxT("invalid font") );
816 /* CMB 21/5/98: draw text background if mode is wxSOLID */
817 if (m_backgroundMode
== wxSOLID
)
819 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
820 wxCoord height
= font
->ascent
+ font
->descent
;
821 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
822 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
823 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
825 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
827 /* CMB 17/7/98: simple underline: ignores scaling and underlying
828 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
829 properties (see wxXt implementation) */
830 if (m_font
.GetUnderlined())
832 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
833 wxCoord ul_y
= y
+ font
->ascent
;
834 if (font
->descent
> 0) ul_y
++;
835 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
839 GetTextExtent (text
, &w
, &h
);
840 CalcBoundingBox (x
+ w
, y
+ h
);
841 CalcBoundingBox (x
, y
);
844 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
848 DrawText(text
, x
, y
);
852 wxCHECK_RET( Ok(), wxT("invalid window dc") );
854 if (!m_window
) return;
856 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
858 wxCHECK_RET( font
, wxT("invalid font") );
860 // the size of the text
861 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
862 wxCoord h
= font
->ascent
+ font
->descent
;
864 // draw the string normally
867 dc
.SelectObject(src
);
868 dc
.SetFont(GetFont());
869 dc
.SetBackground(*wxWHITE_BRUSH
);
870 dc
.SetBrush(*wxBLACK_BRUSH
);
872 dc
.DrawText(text
, 0, 0);
873 dc
.SetFont(wxNullFont
);
874 dc
.SelectObject(wxNullBitmap
);
876 // Calculate the size of the rotated bounding box.
877 double rad
= DegToRad(angle
);
878 double dx
= cos(rad
),
881 // the rectngle vertices are counted clockwise with the first one being at
882 // (0, 0) (or, rather, at (x, y))
884 y2
= -w
*dy
; // y axis points to the bottom, hence minus
891 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
892 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
893 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
894 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
896 // prepare to blit-with-rotate the bitmap to the DC
899 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
900 *colBack
= m_textBackgroundColour
.GetColor();
902 bool textColSet
= TRUE
;
904 unsigned char *data
= image
.GetData();
906 // paint pixel by pixel
907 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
909 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
911 // transform source coords to dest coords
912 double r
= sqrt(srcX
*srcX
+ srcY
*srcY
);
913 double angleOrig
= atan2(srcY
, srcX
) - rad
;
914 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
915 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
918 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
919 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
921 // change colour if needed
922 if ( textPixel
!= textColSet
)
924 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
927 textColSet
= textPixel
;
930 // don't use DrawPoint() because it uses the current pen
931 // colour, and we don't need it here
932 gdk_draw_point( m_window
, m_textGC
,
933 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
938 // it would be better to draw with non underlined font and draw the line
939 // manually here (it would be more straight...)
941 if ( m_font
.GetUnderlined() )
943 gdk_draw_line( m_window
, m_textGC
,
944 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
945 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
949 // restore the font colour
950 gdk_gc_set_foreground( m_textGC
, colText
);
952 // update the bounding box
953 CalcBoundingBox(x
+ minX
, y
+ minY
);
954 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
957 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
958 wxCoord
*width
, wxCoord
*height
,
959 wxCoord
*descent
, wxCoord
*externalLeading
,
960 wxFont
*theFont
) const
962 wxFont fontToUse
= m_font
;
963 if (theFont
) fontToUse
= *theFont
;
965 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
966 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
967 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
968 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
969 if (externalLeading
) (*externalLeading
) = 0; // ??
972 wxCoord
wxWindowDC::GetCharWidth() const
974 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
975 wxCHECK_MSG( font
, -1, wxT("invalid font") );
977 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
980 wxCoord
wxWindowDC::GetCharHeight() const
982 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
983 wxCHECK_MSG( font
, -1, wxT("invalid font") );
985 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
988 void wxWindowDC::Clear()
990 wxCHECK_RET( Ok(), wxT("invalid window dc") );
992 if (!m_window
) return;
994 /* - we either are a memory dc or have a window as the
995 owner. anything else shouldn't happen.
996 - we don't use gdk_window_clear() as we don't set
997 the window's background colour anymore. it is too
998 much pain to keep the DC's and the window's back-
999 ground colour in synch. */
1004 m_owner
->GetSize( &width
, &height
);
1005 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1012 GetSize( &width
, &height
);
1013 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
1018 void wxWindowDC::SetFont( const wxFont
&font
)
1023 void wxWindowDC::SetPen( const wxPen
&pen
)
1025 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1027 if (m_pen
== pen
) return;
1031 if (!m_pen
.Ok()) return;
1033 if (!m_window
) return;
1035 gint width
= m_pen
.GetWidth();
1038 // CMB: if width is non-zero scale it with the dc
1043 // X doesn't allow different width in x and y and so we take
1046 ( fabs((double) XLOG2DEVREL(width
)) +
1047 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1051 static const char dotted
[] = {1, 1};
1052 static const char short_dashed
[] = {2, 2};
1053 static const char wxCoord_dashed
[] = {2, 4};
1054 static const char dotted_dashed
[] = {3, 3, 1, 3};
1056 // We express dash pattern in pen width unit, so we are
1057 // independent of zoom factor and so on...
1059 const char *req_dash
;
1061 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1062 switch (m_pen
.GetStyle())
1066 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1067 req_nb_dash
= m_pen
.GetDashCount();
1068 req_dash
= m_pen
.GetDash();
1073 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1080 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1082 req_dash
= wxCoord_dashed
;
1087 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1089 req_dash
= short_dashed
;
1094 // lineStyle = GDK_LINE_DOUBLE_DASH;
1095 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1097 req_dash
= dotted_dashed
;
1102 case wxSTIPPLE_MASK_OPAQUE
:
1107 lineStyle
= GDK_LINE_SOLID
;
1108 req_dash
= (wxDash
*)NULL
;
1114 #if (GTK_MINOR_VERSION > 0)
1115 if (req_dash
&& req_nb_dash
)
1117 char *real_req_dash
= new char[req_nb_dash
];
1120 for (int i
= 0; i
< req_nb_dash
; i
++)
1121 real_req_dash
[i
] = req_dash
[i
] * width
;
1122 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1123 delete[] real_req_dash
;
1127 // No Memory. We use non-scaled dash pattern...
1128 gdk_gc_set_dashes( m_penGC
, 0, (char*)req_dash
, req_nb_dash
);
1133 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1134 switch (m_pen
.GetCap())
1136 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1137 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1144 capStyle
= GDK_CAP_NOT_LAST
;
1148 capStyle
= GDK_CAP_ROUND
;
1154 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1155 switch (m_pen
.GetJoin())
1157 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1158 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1160 default: { joinStyle
= GDK_JOIN_ROUND
; break; }
1163 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1165 m_pen
.GetColour().CalcPixel( m_cmap
);
1166 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1169 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1171 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1173 if (m_brush
== brush
) return;
1177 if (!m_brush
.Ok()) return;
1179 if (!m_window
) return;
1181 m_brush
.GetColour().CalcPixel( m_cmap
);
1182 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1184 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1186 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1188 if (m_brush
.GetStipple()->GetPixmap())
1190 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1191 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1195 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1196 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1200 if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask()))
1202 gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
);
1203 gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() );
1206 if (IS_HATCH(m_brush
.GetStyle()))
1208 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1209 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1210 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1214 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1216 /* CMB 21/7/98: Added SetBackground. Sets background brush
1217 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1219 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1221 if (m_backgroundBrush
== brush
) return;
1223 m_backgroundBrush
= brush
;
1225 if (!m_backgroundBrush
.Ok()) return;
1227 if (!m_window
) return;
1229 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1230 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1231 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1232 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1233 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1235 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1237 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1239 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1241 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1242 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1246 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1247 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1251 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1253 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1254 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1255 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1259 void wxWindowDC::SetLogicalFunction( int function
)
1261 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1263 if (m_logicalFunction
== function
) return;
1265 GdkFunction mode
= GDK_COPY
;
1268 case wxXOR
: mode
= GDK_XOR
; break;
1269 case wxINVERT
: mode
= GDK_INVERT
; break;
1270 #if (GTK_MINOR_VERSION > 0)
1271 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1272 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1273 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1274 case wxSET
: mode
= GDK_SET
; break;
1275 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1277 case wxAND
: mode
= GDK_AND
; break;
1279 case wxOR
: mode
= GDK_OR
; break;
1280 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1281 case wxNAND
: mode
= GDK_NAND
; break;
1282 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1283 case wxCOPY
: mode
= GDK_COPY
; break;
1284 case wxNO_OP
: mode
= GDK_NOOP
; break;
1285 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1289 wxFAIL_MSG( wxT("unsupported logical function") );
1294 m_logicalFunction
= function
;
1296 if (!m_window
) return;
1298 gdk_gc_set_function( m_penGC
, mode
);
1299 gdk_gc_set_function( m_brushGC
, mode
);
1300 gdk_gc_set_function( m_textGC
, mode
);
1303 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1305 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1307 if (m_textForegroundColour
== col
) return;
1309 m_textForegroundColour
= col
;
1310 if (!m_textForegroundColour
.Ok()) return;
1312 if (!m_window
) return;
1314 m_textForegroundColour
.CalcPixel( m_cmap
);
1315 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1318 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1320 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1322 if (m_textBackgroundColour
== col
) return;
1324 m_textBackgroundColour
= col
;
1325 if (!m_textBackgroundColour
.Ok()) return;
1327 if (!m_window
) return;
1329 m_textBackgroundColour
.CalcPixel( m_cmap
);
1330 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1333 void wxWindowDC::SetBackgroundMode( int mode
)
1335 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1337 m_backgroundMode
= mode
;
1339 if (!m_window
) return;
1341 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1342 // transparent/solid background mode
1344 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1346 gdk_gc_set_fill( m_brushGC
,
1347 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1351 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1353 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1356 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1358 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1360 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1362 if (!m_window
) return;
1365 rect
.x
= XLOG2DEV(x
);
1366 rect
.y
= YLOG2DEV(y
);
1367 rect
.width
= XLOG2DEVREL(width
);
1368 rect
.height
= YLOG2DEVREL(height
);
1369 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1370 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1371 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1372 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1375 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1377 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1381 DestroyClippingRegion();
1385 if (!m_window
) return;
1387 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1388 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1389 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1390 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1393 void wxWindowDC::DestroyClippingRegion()
1395 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1397 wxDC::DestroyClippingRegion();
1399 if (!m_window
) return;
1401 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1402 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1403 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1404 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1407 void wxWindowDC::SetUpDC()
1411 m_logicalFunction
= wxCOPY
;
1412 m_penGC
= gdk_gc_new( m_window
);
1413 m_brushGC
= gdk_gc_new( m_window
);
1414 m_textGC
= gdk_gc_new( m_window
);
1415 m_bgGC
= gdk_gc_new( m_window
);
1417 wxColour
tmp_col( m_textForegroundColour
);
1418 m_textForegroundColour
= wxNullColour
;
1419 SetTextForeground( tmp_col
);
1420 tmp_col
= m_textBackgroundColour
;
1421 m_textBackgroundColour
= wxNullColour
;
1422 SetTextBackground( tmp_col
);
1424 wxPen
tmp_pen( m_pen
);
1428 wxFont
tmp_font( m_font
);
1429 m_font
= wxNullFont
;
1430 SetFont( tmp_font
);
1432 wxBrush
tmp_brush( m_brush
);
1433 m_brush
= wxNullBrush
;
1434 SetBrush( tmp_brush
);
1437 tmp_brush = m_backgroundBrush;
1438 m_backgroundBrush = wxNullBrush;
1439 SetBackground( tmp_brush );
1441 tmp_brush
= m_backgroundBrush
;
1442 m_backgroundBrush
= wxNullBrush
;
1443 SetBackground( *wxWHITE_BRUSH
);
1444 m_backgroundBrush
= tmp_brush
;
1448 hatch_bitmap
= hatches
;
1449 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1450 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1451 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1452 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1453 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1454 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1458 void wxWindowDC::Destroy()
1460 if (m_penGC
) gdk_gc_unref( m_penGC
);
1461 m_penGC
= (GdkGC
*) NULL
;
1462 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1463 m_brushGC
= (GdkGC
*) NULL
;
1464 if (m_textGC
) gdk_gc_unref( m_textGC
);
1465 m_textGC
= (GdkGC
*) NULL
;
1466 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1467 m_bgGC
= (GdkGC
*) NULL
;
1470 void wxWindowDC::ComputeScaleAndOrigin()
1472 /* CMB: copy scale to see if it changes */
1473 double origScaleX
= m_scaleX
;
1474 double origScaleY
= m_scaleY
;
1476 wxDC::ComputeScaleAndOrigin();
1478 /* CMB: if scale has changed call SetPen to recalulate the line width */
1479 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1482 /* this is a bit artificial, but we need to force wxDC to think
1483 the pen has changed */
1490 // Resolution in pixels per logical inch
1491 wxSize
wxWindowDC::GetPPI() const
1493 return wxSize(100, 100);
1496 int wxWindowDC::GetDepth() const
1498 wxFAIL_MSG(wxT("not implemented"));
1504 // ----------------------------------- spline code ----------------------------------------
1506 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1507 double a3
, double b3
, double a4
, double b4
);
1508 void wx_clear_stack();
1509 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1510 double *y3
, double *x4
, double *y4
);
1511 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1512 double x4
, double y4
);
1513 static bool wx_spline_add_point(double x
, double y
);
1514 static void wx_spline_draw_point_array(wxDC
*dc
);
1516 wxList wx_spline_point_list
;
1518 #define half(z1, z2) ((z1+z2)/2.0)
1521 /* iterative version */
1523 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1526 register double xmid
, ymid
;
1527 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1530 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1532 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1533 xmid
= (double)half(x2
, x3
);
1534 ymid
= (double)half(y2
, y3
);
1535 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1536 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1537 wx_spline_add_point( x1
, y1
);
1538 wx_spline_add_point( xmid
, ymid
);
1540 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1541 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1542 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1543 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1548 /* utilities used by spline drawing routines */
1550 typedef struct wx_spline_stack_struct
{
1551 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1554 #define SPLINE_STACK_DEPTH 20
1555 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1556 static Stack
*wx_stack_top
;
1557 static int wx_stack_count
;
1559 void wx_clear_stack()
1561 wx_stack_top
= wx_spline_stack
;
1565 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1567 wx_stack_top
->x1
= x1
;
1568 wx_stack_top
->y1
= y1
;
1569 wx_stack_top
->x2
= x2
;
1570 wx_stack_top
->y2
= y2
;
1571 wx_stack_top
->x3
= x3
;
1572 wx_stack_top
->y3
= y3
;
1573 wx_stack_top
->x4
= x4
;
1574 wx_stack_top
->y4
= y4
;
1579 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1580 double *x3
, double *y3
, double *x4
, double *y4
)
1582 if (wx_stack_count
== 0)
1586 *x1
= wx_stack_top
->x1
;
1587 *y1
= wx_stack_top
->y1
;
1588 *x2
= wx_stack_top
->x2
;
1589 *y2
= wx_stack_top
->y2
;
1590 *x3
= wx_stack_top
->x3
;
1591 *y3
= wx_stack_top
->y3
;
1592 *x4
= wx_stack_top
->x4
;
1593 *y4
= wx_stack_top
->y4
;
1597 static bool wx_spline_add_point(double x
, double y
)
1599 wxPoint
*point
= new wxPoint
;
1602 wx_spline_point_list
.Append((wxObject
*)point
);
1606 static void wx_spline_draw_point_array(wxDC
*dc
)
1608 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1609 wxNode
*node
= wx_spline_point_list
.First();
1612 wxPoint
*point
= (wxPoint
*)node
->Data();
1615 node
= wx_spline_point_list
.First();
1619 void wxWindowDC::DoDrawSpline( wxList
*points
)
1621 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1624 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1625 double x1
, y1
, x2
, y2
;
1627 wxNode
*node
= points
->First();
1628 p
= (wxPoint
*)node
->Data();
1633 node
= node
->Next();
1634 p
= (wxPoint
*)node
->Data();
1638 cx1
= (double)((x1
+ x2
) / 2);
1639 cy1
= (double)((y1
+ y2
) / 2);
1640 cx2
= (double)((cx1
+ x2
) / 2);
1641 cy2
= (double)((cy1
+ y2
) / 2);
1643 wx_spline_add_point(x1
, y1
);
1645 while ((node
= node
->Next()) != NULL
)
1647 p
= (wxPoint
*)node
->Data();
1652 cx4
= (double)(x1
+ x2
) / 2;
1653 cy4
= (double)(y1
+ y2
) / 2;
1654 cx3
= (double)(x1
+ cx4
) / 2;
1655 cy3
= (double)(y1
+ cy4
) / 2;
1657 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1661 cx2
= (double)(cx1
+ x2
) / 2;
1662 cy2
= (double)(cy1
+ y2
) / 2;
1665 wx_spline_add_point( cx1
, cy1
);
1666 wx_spline_add_point( x2
, y2
);
1668 wx_spline_draw_point_array( this );
1671 #endif // wxUSE_SPLINE
1673 //-----------------------------------------------------------------------------
1675 //-----------------------------------------------------------------------------
1677 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1679 wxPaintDC::wxPaintDC()
1684 wxPaintDC::wxPaintDC( wxWindow
*win
)
1689 //-----------------------------------------------------------------------------
1691 //-----------------------------------------------------------------------------
1693 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1695 wxClientDC::wxClientDC()
1700 wxClientDC::wxClientDC( wxWindow
*win
)