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
);
342 if ((m_brush
.GetStyle() != wxTRANSPARENT
) && m_window
)
343 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
347 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
349 for (i
= 0 ; i
< n
; i
++)
351 gdk_draw_line( m_window
, m_penGC
,
354 gdkpoints
[(i
+1)%n
].x
,
355 gdkpoints
[(i
+1)%n
].y
);
362 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
364 wxCHECK_RET( Ok(), wxT("invalid window dc") );
366 wxCoord xx
= XLOG2DEV(x
);
367 wxCoord yy
= YLOG2DEV(y
);
368 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
369 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
371 // CMB: draw nothing if transformed w or h is 0
372 if (ww
== 0 || hh
== 0) return;
374 // CMB: handle -ve width and/or height
375 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
376 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
380 if (m_brush
.GetStyle() != wxTRANSPARENT
)
381 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
383 if (m_pen
.GetStyle() != wxTRANSPARENT
)
384 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
387 CalcBoundingBox( x
, y
);
388 CalcBoundingBox( x
+ width
, y
+ height
);
391 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
393 wxCHECK_RET( Ok(), wxT("invalid window dc") );
395 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
397 wxCoord xx
= XLOG2DEV(x
);
398 wxCoord yy
= YLOG2DEV(y
);
399 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
400 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
401 wxCoord rr
= XLOG2DEVREL((wxCoord
)radius
);
403 // CMB: handle -ve width and/or height
404 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
405 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
407 // CMB: if radius is zero use DrawRectangle() instead to avoid
408 // X drawing errors with small radii
411 DrawRectangle( x
, y
, width
, height
);
415 // CMB: draw nothing if transformed w or h is 0
416 if (ww
== 0 || hh
== 0) return;
418 // CMB: adjust size if outline is drawn otherwise the result is
419 // 1 pixel too wide and high
420 if (m_pen
.GetStyle() != wxTRANSPARENT
)
428 // CMB: ensure dd is not larger than rectangle otherwise we
429 // get an hour glass shape
431 if (dd
> ww
) dd
= ww
;
432 if (dd
> hh
) dd
= hh
;
435 if (m_brush
.GetStyle() != wxTRANSPARENT
)
437 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
438 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
439 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
440 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
441 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
442 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
445 if (m_pen
.GetStyle() != wxTRANSPARENT
)
447 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
448 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
449 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
450 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
451 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
452 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
453 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
454 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
458 // this ignores the radius
459 CalcBoundingBox( x
, y
);
460 CalcBoundingBox( x
+ width
, y
+ height
);
463 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
465 wxCHECK_RET( Ok(), wxT("invalid window dc") );
467 wxCoord xx
= XLOG2DEV(x
);
468 wxCoord yy
= YLOG2DEV(y
);
469 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
470 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
472 // CMB: handle -ve width and/or height
473 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
474 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
478 if (m_brush
.GetStyle() != wxTRANSPARENT
)
479 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
481 if (m_pen
.GetStyle() != wxTRANSPARENT
)
482 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
485 CalcBoundingBox( x
- width
, y
- height
);
486 CalcBoundingBox( x
+ width
, y
+ height
);
489 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, wxCoord x
, wxCoord y
)
491 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
492 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
495 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
496 wxCoord x
, wxCoord y
,
499 wxCHECK_RET( Ok(), wxT("invalid window dc") );
501 wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") );
503 /* scale/translate size and position */
505 int xx
= XLOG2DEV(x
);
506 int yy
= YLOG2DEV(y
);
508 int w
= bitmap
.GetWidth();
509 int h
= bitmap
.GetHeight();
511 CalcBoundingBox( x
, y
);
512 CalcBoundingBox( x
+ w
, y
+ h
);
514 if (!m_window
) return;
516 int ww
= XLOG2DEVREL(w
);
517 int hh
= YLOG2DEVREL(h
);
519 /* scale bitmap if required */
523 if ((w
!= ww
) || (h
!= hh
))
525 wxImage
image( bitmap
);
526 image
= image
.Scale( ww
, hh
);
528 use_bitmap
= image
.ConvertToBitmap();
535 /* apply mask if any */
537 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
538 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
542 gdk_gc_set_clip_mask( m_penGC
, mask
);
543 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
546 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
548 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
551 gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 );
555 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
558 gdk_draw_bitmap( m_window
, m_penGC
, bm
, 0, 0, xx
, yy
, -1, -1 );
562 /* remove mask again if any */
566 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
567 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
571 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
572 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
573 int logical_func
, bool useMask
)
575 /* this is the nth try to get this utterly useless function to
576 work. it now completely ignores the scaling or translation
577 of the source dc, but scales correctly on the target dc and
578 knows about possible mask information in a memory dc. */
580 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") );
582 wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") );
584 if (!m_window
) return FALSE
;
586 wxClientDC
*srcDC
= (wxClientDC
*)source
;
587 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
589 bool use_bitmap_method
= FALSE
;
591 if (srcDC
->m_isMemDC
)
593 if (!memDC
->m_selected
.Ok()) return FALSE
;
595 /* we use the "XCopyArea" way to copy a memory dc into
596 y different window if the memory dc BOTH
597 a) doesn't have any mask or its mask isn't used
601 if (useMask
&& (memDC
->m_selected
.GetMask()))
603 /* we HAVE TO use the direct way for memory dcs
604 that have mask since the XCopyArea doesn't know
606 use_bitmap_method
= TRUE
;
608 else if (memDC
->m_selected
.GetDepth() == 1)
610 /* we HAVE TO use the direct way for memory dcs
611 that are bitmaps because XCopyArea doesn't cope
612 with different bit depths */
613 use_bitmap_method
= TRUE
;
615 else if ((xsrc
== 0) && (ysrc
== 0) &&
616 (width
== memDC
->m_selected
.GetWidth()) &&
617 (height
== memDC
->m_selected
.GetHeight()))
619 /* we SHOULD use the direct way if all of the bitmap
620 in the memory dc is copied in which case XCopyArea
621 wouldn't be able able to boost performace by reducing
622 the area to be scaled */
623 use_bitmap_method
= TRUE
;
627 use_bitmap_method
= FALSE
;
631 CalcBoundingBox( xdest
, ydest
);
632 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
634 int old_logical_func
= m_logicalFunction
;
635 SetLogicalFunction( logical_func
);
637 if (use_bitmap_method
)
639 /* scale/translate bitmap size */
641 wxCoord bm_width
= memDC
->m_selected
.GetWidth();
642 wxCoord bm_height
= memDC
->m_selected
.GetHeight();
644 wxCoord bm_ww
= XLOG2DEVREL( bm_width
);
645 wxCoord bm_hh
= YLOG2DEVREL( bm_height
);
647 /* scale bitmap if required */
651 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
653 wxImage
image( memDC
->m_selected
);
654 image
= image
.Scale( bm_ww
, bm_hh
);
656 use_bitmap
= image
.ConvertToBitmap();
660 use_bitmap
= memDC
->m_selected
;
663 /* scale/translate size and position */
665 wxCoord xx
= XLOG2DEV(xdest
);
666 wxCoord yy
= YLOG2DEV(ydest
);
668 wxCoord ww
= XLOG2DEVREL(width
);
669 wxCoord hh
= YLOG2DEVREL(height
);
671 /* apply mask if any */
673 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
674 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
678 gdk_gc_set_clip_mask( m_penGC
, mask
);
679 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
682 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
684 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
687 gdk_draw_pixmap( m_window
, m_penGC
, pm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
691 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
694 /* we use the textGC here because blitting a bitmap is done
695 using the current text colour */
696 gdk_draw_bitmap( m_window
, m_textGC
, bm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
700 /* remove mask again if any */
704 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
705 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
708 else /* use_bitmap_method */
710 /* scale/translate size and position */
712 wxCoord xx
= XLOG2DEV(xdest
);
713 wxCoord yy
= YLOG2DEV(ydest
);
715 wxCoord ww
= XLOG2DEVREL(width
);
716 wxCoord hh
= YLOG2DEVREL(height
);
718 if ((width
!= ww
) || (height
!= hh
))
720 /* draw source window into a bitmap as we cannot scale
721 a window in contrast to a bitmap. this would actually
722 work with memory dcs as well, but we'd lose the mask
723 information and waste one step in this process since
724 a memory already has a bitmap. all this is slightly
725 inefficient as we could take an XImage directly from
726 an X window, but we'd then also have to care that
727 the window is not outside the screen (in which case
728 we'd get a BadMatch or what not).
729 Is a double XGetImage and combined XGetPixel and
730 XPutPixel really faster? I'm not sure. look at wxXt
731 for a different implementation of the same problem. */
733 wxBitmap
bitmap( width
, height
);
734 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
736 xsrc
, ysrc
, width
, height
);
740 wxImage
image( bitmap
);
741 image
= image
.Scale( ww
, hh
);
743 /* convert to bitmap */
745 bitmap
= image
.ConvertToBitmap();
747 /* draw scaled bitmap */
749 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
754 /* no scaling and not a memory dc with a mask either */
756 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
758 xsrc
, ysrc
, width
, height
);
762 SetLogicalFunction( old_logical_func
);
766 void wxWindowDC::DoDrawText( const wxString
&text
, wxCoord x
, wxCoord y
)
768 wxCHECK_RET( Ok(), wxT("invalid window dc") );
770 if (!m_window
) return;
772 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
774 wxCHECK_RET( font
, wxT("invalid font") );
779 /* CMB 21/5/98: draw text background if mode is wxSOLID */
780 if (m_backgroundMode
== wxSOLID
)
782 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
783 wxCoord height
= font
->ascent
+ font
->descent
;
784 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
785 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
786 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
788 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
790 /* CMB 17/7/98: simple underline: ignores scaling and underlying
791 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
792 properties (see wxXt implementation) */
793 if (m_font
.GetUnderlined())
795 wxCoord width
= gdk_string_width( font
, text
.mbc_str() );
796 wxCoord ul_y
= y
+ font
->ascent
;
797 if (font
->descent
> 0) ul_y
++;
798 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
802 GetTextExtent (text
, &w
, &h
);
803 CalcBoundingBox (x
+ w
, y
+ h
);
804 CalcBoundingBox (x
, y
);
807 void wxWindowDC::DoDrawRotatedText( const wxString
&text
, wxCoord x
, wxCoord y
, double angle
)
811 DrawText(text
, x
, y
);
815 wxCHECK_RET( Ok(), wxT("invalid window dc") );
817 if (!m_window
) return;
819 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
821 wxCHECK_RET( font
, wxT("invalid font") );
823 // the size of the text
824 wxCoord w
= gdk_string_width( font
, text
.mbc_str() );
825 wxCoord h
= font
->ascent
+ font
->descent
;
827 // draw the string normally
830 dc
.SelectObject(src
);
831 dc
.SetFont(GetFont());
832 dc
.SetBackground(*wxWHITE_BRUSH
);
833 dc
.SetBrush(*wxBLACK_BRUSH
);
835 dc
.DrawText(text
, 0, 0);
836 dc
.SetFont(wxNullFont
);
837 dc
.SelectObject(wxNullBitmap
);
839 // Calculate the size of the rotated bounding box.
840 double rad
= DegToRad(angle
);
841 double dx
= cos(rad
),
844 // the rectngle vertices are counted clockwise with the first one being at
845 // (0, 0) (or, rather, at (x, y))
847 y2
= -w
*dy
; // y axis points to the bottom, hence minus
854 wxCoord maxX
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5),
855 maxY
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5),
856 minX
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5),
857 minY
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5);
859 // prepare to blit-with-rotate the bitmap to the DC
862 GdkColor
*colText
= m_textForegroundColour
.GetColor(),
863 *colBack
= m_textBackgroundColour
.GetColor();
865 bool textColSet
= TRUE
;
867 unsigned char *data
= image
.GetData();
869 // paint pixel by pixel
870 for ( wxCoord srcX
= 0; srcX
< w
; srcX
++ )
872 for ( wxCoord srcY
= 0; srcY
< h
; srcY
++ )
874 // transform source coords to dest coords
875 double r
= sqrt(srcX
*srcX
+ srcY
*srcY
);
876 double angleOrig
= atan2(srcY
, srcX
) - rad
;
877 wxCoord dstX
= (wxCoord
)(r
*cos(angleOrig
) + 0.5),
878 dstY
= (wxCoord
)(r
*sin(angleOrig
) + 0.5);
881 bool textPixel
= data
[(srcY
*w
+ srcX
)*3] == 0;
882 if ( textPixel
|| (m_backgroundMode
== wxSOLID
) )
884 // change colour if needed
885 if ( textPixel
!= textColSet
)
887 gdk_gc_set_foreground( m_textGC
, textPixel
? colText
890 textColSet
= textPixel
;
893 // don't use DrawPoint() because it uses the current pen
894 // colour, and we don't need it here
895 gdk_draw_point( m_window
, m_textGC
,
896 XLOG2DEV(x
+ dstX
), YLOG2DEV(y
+ dstY
) );
901 // it would be better to draw with non underlined font and draw the line
902 // manually here (it would be more straight...)
904 if ( m_font
.GetUnderlined() )
906 gdk_draw_line( m_window
, m_textGC
,
907 XLOG2DEV(x
+ x4
), YLOG2DEV(y
+ y4
+ font
->descent
),
908 XLOG2DEV(x
+ x3
), YLOG2DEV(y
+ y3
+ font
->descent
));
912 // restore the font colour
913 gdk_gc_set_foreground( m_textGC
, colText
);
915 // update the bounding box
916 CalcBoundingBox(x
+ minX
, y
+ minY
);
917 CalcBoundingBox(x
+ maxX
, y
+ maxY
);
920 void wxWindowDC::DoGetTextExtent(const wxString
&string
,
921 wxCoord
*width
, wxCoord
*height
,
922 wxCoord
*descent
, wxCoord
*externalLeading
,
923 wxFont
*theFont
) const
925 wxFont fontToUse
= m_font
;
926 if (theFont
) fontToUse
= *theFont
;
928 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
929 if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
930 if (height
) (*height
) = wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
931 if (descent
) (*descent
) = wxCoord(font
->descent
/ m_scaleY
);
932 if (externalLeading
) (*externalLeading
) = 0; // ??
935 wxCoord
wxWindowDC::GetCharWidth() const
937 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
938 wxCHECK_MSG( font
, -1, wxT("invalid font") );
940 return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
);
943 wxCoord
wxWindowDC::GetCharHeight() const
945 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
946 wxCHECK_MSG( font
, -1, wxT("invalid font") );
948 return wxCoord((font
->ascent
+ font
->descent
) / m_scaleY
);
951 void wxWindowDC::Clear()
953 wxCHECK_RET( Ok(), wxT("invalid window dc") );
955 if (!m_window
) return;
957 /* - we either are a memory dc or have a window as the
958 owner. anything else shouldn't happen.
959 - we don't use gdk_window_clear() as we don't set
960 the window's background colour anymore. it is too
961 much pain to keep the DC's and the window's back-
962 ground colour in synch. */
967 m_owner
->GetSize( &width
, &height
);
968 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
975 GetSize( &width
, &height
);
976 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
981 void wxWindowDC::SetFont( const wxFont
&font
)
986 void wxWindowDC::SetPen( const wxPen
&pen
)
988 wxCHECK_RET( Ok(), wxT("invalid window dc") );
990 if (m_pen
== pen
) return;
994 if (!m_pen
.Ok()) return;
996 if (!m_window
) return;
998 gint width
= m_pen
.GetWidth();
1001 // CMB: if width is non-zero scale it with the dc
1006 // X doesn't allow different width in x and y and so we take
1009 ( fabs((double) XLOG2DEVREL(width
)) +
1010 fabs((double) YLOG2DEVREL(width
)) ) / 2.0;
1014 static const char dotted
[] = {1, 1};
1015 static const char short_dashed
[] = {2, 2};
1016 static const char wxCoord_dashed
[] = {2, 4};
1017 static const char dotted_dashed
[] = {3, 3, 1, 3};
1019 // We express dash pattern in pen width unit, so we are
1020 // independent of zoom factor and so on...
1022 const char *req_dash
;
1024 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
1025 switch (m_pen
.GetStyle())
1029 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1030 req_nb_dash
= m_pen
.GetDashCount();
1031 req_dash
= m_pen
.GetDash();
1036 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1043 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1045 req_dash
= wxCoord_dashed
;
1050 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1052 req_dash
= short_dashed
;
1057 // lineStyle = GDK_LINE_DOUBLE_DASH;
1058 lineStyle
= GDK_LINE_ON_OFF_DASH
;
1060 req_dash
= dotted_dashed
;
1069 lineStyle
= GDK_LINE_SOLID
;
1070 req_dash
= (wxDash
*)NULL
;
1076 #if (GTK_MINOR_VERSION > 0)
1077 if (req_dash
&& req_nb_dash
)
1079 char *real_req_dash
= new char[req_nb_dash
];
1082 for (int i
= 0; i
< req_nb_dash
; i
++)
1083 real_req_dash
[i
] = req_dash
[i
] * width
;
1084 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
1085 delete[] real_req_dash
;
1089 // No Memory. We use non-scaled dash pattern...
1090 gdk_gc_set_dashes( m_penGC
, 0, (char*)req_dash
, req_nb_dash
);
1095 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
1096 switch (m_pen
.GetCap())
1098 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
1099 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
1100 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
1103 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
1104 switch (m_pen
.GetJoin())
1106 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
1107 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
1108 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
1111 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
1113 m_pen
.GetColour().CalcPixel( m_cmap
);
1114 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
1117 void wxWindowDC::SetBrush( const wxBrush
&brush
)
1119 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1121 if (m_brush
== brush
) return;
1125 if (!m_brush
.Ok()) return;
1127 if (!m_window
) return;
1129 m_brush
.GetColour().CalcPixel( m_cmap
);
1130 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
1132 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1134 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1136 if (m_brush
.GetStipple()->GetPixmap())
1138 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1139 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1143 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1144 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1148 if (IS_HATCH(m_brush
.GetStyle()))
1150 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1151 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1152 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1156 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1158 /* CMB 21/7/98: Added SetBackground. Sets background brush
1159 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1161 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1163 if (m_backgroundBrush
== brush
) return;
1165 m_backgroundBrush
= brush
;
1167 if (!m_backgroundBrush
.Ok()) return;
1169 if (!m_window
) return;
1171 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1172 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1173 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1174 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1175 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1177 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1179 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1181 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1183 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1184 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1188 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1189 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1193 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1195 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1196 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1197 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1201 void wxWindowDC::SetLogicalFunction( int function
)
1203 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1205 if (m_logicalFunction
== function
) return;
1207 GdkFunction mode
= GDK_COPY
;
1210 case wxXOR
: mode
= GDK_XOR
; break;
1211 case wxINVERT
: mode
= GDK_INVERT
; break;
1212 #if (GTK_MINOR_VERSION > 0)
1213 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1214 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1215 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1216 case wxSET
: mode
= GDK_SET
; break;
1217 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1219 case wxAND
: mode
= GDK_AND
; break;
1221 case wxOR
: mode
= GDK_OR
; break;
1222 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1223 case wxNAND
: mode
= GDK_NAND
; break;
1224 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1225 case wxCOPY
: mode
= GDK_COPY
; break;
1226 case wxNO_OP
: mode
= GDK_NOOP
; break;
1227 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1231 wxFAIL_MSG( wxT("unsupported logical function") );
1236 m_logicalFunction
= function
;
1238 if (!m_window
) return;
1240 gdk_gc_set_function( m_penGC
, mode
);
1241 gdk_gc_set_function( m_brushGC
, mode
);
1242 gdk_gc_set_function( m_textGC
, mode
);
1245 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1247 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1249 if (m_textForegroundColour
== col
) return;
1251 m_textForegroundColour
= col
;
1252 if (!m_textForegroundColour
.Ok()) return;
1254 if (!m_window
) return;
1256 m_textForegroundColour
.CalcPixel( m_cmap
);
1257 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1260 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1262 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1264 if (m_textBackgroundColour
== col
) return;
1266 m_textBackgroundColour
= col
;
1267 if (!m_textBackgroundColour
.Ok()) return;
1269 if (!m_window
) return;
1271 m_textBackgroundColour
.CalcPixel( m_cmap
);
1272 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1275 void wxWindowDC::SetBackgroundMode( int mode
)
1277 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1279 m_backgroundMode
= mode
;
1281 if (!m_window
) return;
1283 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1284 // transparent/solid background mode
1286 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1288 gdk_gc_set_fill( m_brushGC
,
1289 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1293 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1295 wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
1298 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
1300 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1302 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1304 if (!m_window
) return;
1307 rect
.x
= XLOG2DEV(x
);
1308 rect
.y
= YLOG2DEV(y
);
1309 rect
.width
= XLOG2DEVREL(width
);
1310 rect
.height
= YLOG2DEVREL(height
);
1311 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1312 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1313 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1314 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1317 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1319 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1323 DestroyClippingRegion();
1327 if (!m_window
) return;
1329 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1330 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1331 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1332 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1335 void wxWindowDC::DestroyClippingRegion()
1337 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1339 wxDC::DestroyClippingRegion();
1341 if (!m_window
) return;
1343 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1344 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1345 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1346 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1349 void wxWindowDC::SetUpDC()
1353 m_logicalFunction
= wxCOPY
;
1354 m_penGC
= gdk_gc_new( m_window
);
1355 m_brushGC
= gdk_gc_new( m_window
);
1356 m_textGC
= gdk_gc_new( m_window
);
1357 m_bgGC
= gdk_gc_new( m_window
);
1359 wxColour
tmp_col( m_textForegroundColour
);
1360 m_textForegroundColour
= wxNullColour
;
1361 SetTextForeground( tmp_col
);
1362 tmp_col
= m_textBackgroundColour
;
1363 m_textBackgroundColour
= wxNullColour
;
1364 SetTextBackground( tmp_col
);
1366 wxPen
tmp_pen( m_pen
);
1370 wxFont
tmp_font( m_font
);
1371 m_font
= wxNullFont
;
1372 SetFont( tmp_font
);
1374 wxBrush
tmp_brush( m_brush
);
1375 m_brush
= wxNullBrush
;
1376 SetBrush( tmp_brush
);
1379 tmp_brush = m_backgroundBrush;
1380 m_backgroundBrush = wxNullBrush;
1381 SetBackground( tmp_brush );
1383 tmp_brush
= m_backgroundBrush
;
1384 m_backgroundBrush
= wxNullBrush
;
1385 SetBackground( *wxWHITE_BRUSH
);
1386 m_backgroundBrush
= tmp_brush
;
1390 hatch_bitmap
= hatches
;
1391 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1392 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1393 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1394 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1395 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1396 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1400 void wxWindowDC::Destroy()
1402 if (m_penGC
) gdk_gc_unref( m_penGC
);
1403 m_penGC
= (GdkGC
*) NULL
;
1404 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1405 m_brushGC
= (GdkGC
*) NULL
;
1406 if (m_textGC
) gdk_gc_unref( m_textGC
);
1407 m_textGC
= (GdkGC
*) NULL
;
1408 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1409 m_bgGC
= (GdkGC
*) NULL
;
1412 void wxWindowDC::ComputeScaleAndOrigin()
1414 /* CMB: copy scale to see if it changes */
1415 double origScaleX
= m_scaleX
;
1416 double origScaleY
= m_scaleY
;
1418 wxDC::ComputeScaleAndOrigin();
1420 /* CMB: if scale has changed call SetPen to recalulate the line width */
1421 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1424 /* this is a bit artificial, but we need to force wxDC to think
1425 the pen has changed */
1432 // Resolution in pixels per logical inch
1433 wxSize
wxWindowDC::GetPPI() const
1435 return wxSize(100, 100);
1438 int wxWindowDC::GetDepth() const
1440 wxFAIL_MSG(wxT("not implemented"));
1446 // ----------------------------------- spline code ----------------------------------------
1448 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1449 double a3
, double b3
, double a4
, double b4
);
1450 void wx_clear_stack();
1451 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1452 double *y3
, double *x4
, double *y4
);
1453 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1454 double x4
, double y4
);
1455 static bool wx_spline_add_point(double x
, double y
);
1456 static void wx_spline_draw_point_array(wxDC
*dc
);
1458 wxList wx_spline_point_list
;
1460 #define half(z1, z2) ((z1+z2)/2.0)
1463 /* iterative version */
1465 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1468 register double xmid
, ymid
;
1469 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1472 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1474 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1475 xmid
= (double)half(x2
, x3
);
1476 ymid
= (double)half(y2
, y3
);
1477 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1478 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1479 wx_spline_add_point( x1
, y1
);
1480 wx_spline_add_point( xmid
, ymid
);
1482 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1483 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1484 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1485 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1490 /* utilities used by spline drawing routines */
1492 typedef struct wx_spline_stack_struct
{
1493 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1496 #define SPLINE_STACK_DEPTH 20
1497 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1498 static Stack
*wx_stack_top
;
1499 static int wx_stack_count
;
1501 void wx_clear_stack()
1503 wx_stack_top
= wx_spline_stack
;
1507 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1509 wx_stack_top
->x1
= x1
;
1510 wx_stack_top
->y1
= y1
;
1511 wx_stack_top
->x2
= x2
;
1512 wx_stack_top
->y2
= y2
;
1513 wx_stack_top
->x3
= x3
;
1514 wx_stack_top
->y3
= y3
;
1515 wx_stack_top
->x4
= x4
;
1516 wx_stack_top
->y4
= y4
;
1521 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1522 double *x3
, double *y3
, double *x4
, double *y4
)
1524 if (wx_stack_count
== 0)
1528 *x1
= wx_stack_top
->x1
;
1529 *y1
= wx_stack_top
->y1
;
1530 *x2
= wx_stack_top
->x2
;
1531 *y2
= wx_stack_top
->y2
;
1532 *x3
= wx_stack_top
->x3
;
1533 *y3
= wx_stack_top
->y3
;
1534 *x4
= wx_stack_top
->x4
;
1535 *y4
= wx_stack_top
->y4
;
1539 static bool wx_spline_add_point(double x
, double y
)
1541 wxPoint
*point
= new wxPoint
;
1544 wx_spline_point_list
.Append((wxObject
*)point
);
1548 static void wx_spline_draw_point_array(wxDC
*dc
)
1550 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1551 wxNode
*node
= wx_spline_point_list
.First();
1554 wxPoint
*point
= (wxPoint
*)node
->Data();
1557 node
= wx_spline_point_list
.First();
1561 void wxWindowDC::DoDrawSpline( wxList
*points
)
1563 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1566 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1567 double x1
, y1
, x2
, y2
;
1569 wxNode
*node
= points
->First();
1570 p
= (wxPoint
*)node
->Data();
1575 node
= node
->Next();
1576 p
= (wxPoint
*)node
->Data();
1580 cx1
= (double)((x1
+ x2
) / 2);
1581 cy1
= (double)((y1
+ y2
) / 2);
1582 cx2
= (double)((cx1
+ x2
) / 2);
1583 cy2
= (double)((cy1
+ y2
) / 2);
1585 wx_spline_add_point(x1
, y1
);
1587 while ((node
= node
->Next()) != NULL
)
1589 p
= (wxPoint
*)node
->Data();
1594 cx4
= (double)(x1
+ x2
) / 2;
1595 cy4
= (double)(y1
+ y2
) / 2;
1596 cx3
= (double)(x1
+ cx4
) / 2;
1597 cy3
= (double)(y1
+ cy4
) / 2;
1599 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1603 cx2
= (double)(cx1
+ x2
) / 2;
1604 cy2
= (double)(cy1
+ y2
) / 2;
1607 wx_spline_add_point( cx1
, cy1
);
1608 wx_spline_add_point( x2
, y2
);
1610 wx_spline_draw_point_array( this );
1613 #endif // wxUSE_SPLINE
1615 //-----------------------------------------------------------------------------
1617 //-----------------------------------------------------------------------------
1619 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1621 wxPaintDC::wxPaintDC()
1626 wxPaintDC::wxPaintDC( wxWindow
*win
)
1631 //-----------------------------------------------------------------------------
1633 //-----------------------------------------------------------------------------
1635 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1637 wxClientDC::wxClientDC()
1642 wxClientDC::wxClientDC( wxWindow
*win
)