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"
22 //-----------------------------------------------------------------------------
24 //-----------------------------------------------------------------------------
34 static GdkPixmap
*hatches
[num_hatches
];
35 static GdkPixmap
**hatch_bitmap
= (GdkPixmap
**) NULL
;
37 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
41 #define RAD2DEG 57.2957795131
43 //-----------------------------------------------------------------------------
44 // temporary implementation of the missing GDK function
45 //-----------------------------------------------------------------------------
47 #include "gdk/gdkprivate.h"
49 void gdk_draw_bitmap (GdkDrawable
*drawable
,
59 GdkWindowPrivate
*drawable_private
;
60 GdkWindowPrivate
*src_private
;
61 GdkGCPrivate
*gc_private
;
63 g_return_if_fail (drawable
!= NULL
);
64 g_return_if_fail (src
!= NULL
);
65 g_return_if_fail (gc
!= NULL
);
67 drawable_private
= (GdkWindowPrivate
*) drawable
;
68 src_private
= (GdkWindowPrivate
*) src
;
69 if (drawable_private
->destroyed
|| src_private
->destroyed
)
72 gc_private
= (GdkGCPrivate
*) gc
;
74 if (width
== -1) width
= src_private
->width
;
75 if (height
== -1) height
= src_private
->height
;
77 XCopyPlane( drawable_private
->xdisplay
,
79 drawable_private
->xwindow
,
87 //-----------------------------------------------------------------------------
89 //-----------------------------------------------------------------------------
91 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
93 wxWindowDC::wxWindowDC()
95 m_penGC
= (GdkGC
*) NULL
;
96 m_brushGC
= (GdkGC
*) NULL
;
97 m_textGC
= (GdkGC
*) NULL
;
98 m_bgGC
= (GdkGC
*) NULL
;
99 m_cmap
= (GdkColormap
*) NULL
;
101 m_owner
= (wxWindow
*)NULL
;
104 wxWindowDC::wxWindowDC( wxWindow
*window
)
106 m_penGC
= (GdkGC
*) NULL
;
107 m_brushGC
= (GdkGC
*) NULL
;
108 m_textGC
= (GdkGC
*) NULL
;
109 m_bgGC
= (GdkGC
*) NULL
;
110 m_cmap
= (GdkColormap
*) NULL
;
111 m_owner
= (wxWindow
*)NULL
;
113 m_font
= window
->GetFont();
115 wxASSERT_MSG( window
, _T("DC needs a window") );
117 GtkWidget
*widget
= window
->m_wxwindow
;
119 wxASSERT_MSG( widget
, _T("DC needs a widget") );
121 m_window
= widget
->window
;
126 /* don't report problems */
132 if (window
->m_wxwindow
)
133 m_cmap
= gtk_widget_get_colormap( window
->m_wxwindow
);
135 m_cmap
= gtk_widget_get_colormap( window
->m_widget
);
139 /* this must be done after SetUpDC, bacause SetUpDC calls the
140 repective SetBrush, SetPen, SetBackground etc functions
141 to set up the DC. SetBackground call m_owner->SetBackground
142 and this might not be desired as the standard dc background
143 is white whereas a window might assume gray to be the
144 standard (as e.g. wxStatusBar) */
149 wxWindowDC::~wxWindowDC()
154 void wxWindowDC::DoFloodFill( long WXUNUSED(x
), long WXUNUSED(y
),
155 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
157 wxFAIL_MSG( _T("wxWindowDC::DoFloodFill not implemented") );
160 bool wxWindowDC::DoGetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
162 wxFAIL_MSG( _T("wxWindowDC::DoGetPixel not implemented") );
166 void wxWindowDC::DoDrawLine( long x1
, long y1
, long x2
, long y2
)
168 wxCHECK_RET( Ok(), _T("invalid window dc") );
170 if (m_pen
.GetStyle() != wxTRANSPARENT
)
173 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
175 CalcBoundingBox(x1
, y1
);
176 CalcBoundingBox(x2
, y2
);
180 void wxWindowDC::DoCrossHair( long x
, long y
)
182 wxCHECK_RET( Ok(), _T("invalid window dc") );
184 if (m_pen
.GetStyle() != wxTRANSPARENT
)
189 long xx
= XLOG2DEV(x
);
190 long yy
= YLOG2DEV(y
);
193 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
194 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
199 void wxWindowDC::DoDrawArc( long x1
, long y1
, long x2
, long y2
,
202 wxCHECK_RET( Ok(), _T("invalid window dc") );
204 long xx1
= XLOG2DEV(x1
);
205 long yy1
= YLOG2DEV(y1
);
206 long xx2
= XLOG2DEV(x2
);
207 long yy2
= YLOG2DEV(y2
);
208 long xxc
= XLOG2DEV(xc
);
209 long yyc
= YLOG2DEV(yc
);
210 double dx
= xx1
- xxc
;
211 double dy
= yy1
- yyc
;
212 double radius
= sqrt(dx
*dx
+dy
*dy
);
213 long r
= (long)radius
;
214 double radius1
, radius2
;
216 if (xx1
== xx2
&& yy1
== yy2
)
224 radius1
= radius2
= 0.0;
228 radius1
= (xx1
- xxc
== 0) ?
229 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
230 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
231 radius2
= (xx2
- xxc
== 0) ?
232 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
233 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
235 long alpha1
= long(radius1
* 64.0);
236 long alpha2
= long((radius2
- radius1
) * 64.0);
237 while (alpha2
<= 0) alpha2
+= 360*64;
238 while (alpha1
> 360*64) alpha1
-= 360*64;
242 if (m_brush
.GetStyle() != wxTRANSPARENT
)
243 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
245 if (m_pen
.GetStyle() != wxTRANSPARENT
)
246 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
249 CalcBoundingBox (x1
, y1
);
250 CalcBoundingBox (x2
, y2
);
253 void wxWindowDC::DoDrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
255 wxCHECK_RET( Ok(), _T("invalid window dc") );
257 long xx
= XLOG2DEV(x
);
258 long yy
= YLOG2DEV(y
);
259 long ww
= m_signX
* XLOG2DEVREL(width
);
260 long hh
= m_signY
* YLOG2DEVREL(height
);
262 // CMB: handle -ve width and/or height
263 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
264 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
268 long start
= long(sa
* 64.0);
269 long end
= long(ea
* 64.0);
271 if (m_brush
.GetStyle() != wxTRANSPARENT
)
272 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
274 if (m_pen
.GetStyle() != wxTRANSPARENT
)
275 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
278 CalcBoundingBox (x
, y
);
279 CalcBoundingBox (x
+ width
, y
+ height
);
282 void wxWindowDC::DoDrawPoint( long x
, long y
)
284 wxCHECK_RET( Ok(), _T("invalid window dc") );
286 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
287 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
289 CalcBoundingBox (x
, y
);
292 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
294 wxCHECK_RET( Ok(), _T("invalid window dc") );
296 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
299 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
301 for (int i
= 0; i
< n
-1; i
++)
303 long x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
304 long x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
305 long y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
306 long y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
309 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
311 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
315 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
) )
317 wxCHECK_RET( Ok(), _T("invalid window dc") );
321 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
323 for (i
= 0 ; i
< n
; i
++)
325 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
326 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
328 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
331 if ((m_brush
.GetStyle() != wxTRANSPARENT
) && m_window
)
332 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
336 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
338 for (i
= 0 ; i
< n
; i
++)
340 gdk_draw_line( m_window
, m_penGC
,
343 gdkpoints
[(i
+1)%n
].x
,
344 gdkpoints
[(i
+1)%n
].y
);
351 void wxWindowDC::DoDrawRectangle( long x
, long y
, long width
, long height
)
353 wxCHECK_RET( Ok(), _T("invalid window dc") );
355 long xx
= XLOG2DEV(x
);
356 long yy
= YLOG2DEV(y
);
357 long ww
= m_signX
* XLOG2DEVREL(width
);
358 long hh
= m_signY
* YLOG2DEVREL(height
);
360 // CMB: draw nothing if transformed w or h is 0
361 if (ww
== 0 || hh
== 0) return;
363 // CMB: handle -ve width and/or height
364 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
365 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
369 if (m_brush
.GetStyle() != wxTRANSPARENT
)
370 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
372 if (m_pen
.GetStyle() != wxTRANSPARENT
)
373 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
376 CalcBoundingBox( x
, y
);
377 CalcBoundingBox( x
+ width
, y
+ height
);
380 void wxWindowDC::DoDrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
382 wxCHECK_RET( Ok(), _T("invalid window dc") );
384 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
386 long xx
= XLOG2DEV(x
);
387 long yy
= YLOG2DEV(y
);
388 long ww
= m_signX
* XLOG2DEVREL(width
);
389 long hh
= m_signY
* YLOG2DEVREL(height
);
390 long rr
= XLOG2DEVREL((long)radius
);
392 // CMB: handle -ve width and/or height
393 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
394 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
396 // CMB: if radius is zero use DrawRectangle() instead to avoid
397 // X drawing errors with small radii
400 DrawRectangle( x
, y
, width
, height
);
404 // CMB: draw nothing if transformed w or h is 0
405 if (ww
== 0 || hh
== 0) return;
407 // CMB: adjust size if outline is drawn otherwise the result is
408 // 1 pixel too wide and high
409 if (m_pen
.GetStyle() != wxTRANSPARENT
)
417 // CMB: ensure dd is not larger than rectangle otherwise we
418 // get an hour glass shape
420 if (dd
> ww
) dd
= ww
;
421 if (dd
> hh
) dd
= hh
;
424 if (m_brush
.GetStyle() != wxTRANSPARENT
)
426 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
427 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
428 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
429 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
430 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
431 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
434 if (m_pen
.GetStyle() != wxTRANSPARENT
)
436 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
437 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
438 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
439 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
440 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
441 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
442 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
443 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
447 // this ignores the radius
448 CalcBoundingBox( x
, y
);
449 CalcBoundingBox( x
+ width
, y
+ height
);
452 void wxWindowDC::DoDrawEllipse( long x
, long y
, long width
, long height
)
454 wxCHECK_RET( Ok(), _T("invalid window dc") );
456 long xx
= XLOG2DEV(x
);
457 long yy
= YLOG2DEV(y
);
458 long ww
= m_signX
* XLOG2DEVREL(width
);
459 long hh
= m_signY
* YLOG2DEVREL(height
);
461 // CMB: handle -ve width and/or height
462 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
463 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
467 if (m_brush
.GetStyle() != wxTRANSPARENT
)
468 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
470 if (m_pen
.GetStyle() != wxTRANSPARENT
)
471 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
474 CalcBoundingBox( x
- width
, y
- height
);
475 CalcBoundingBox( x
+ width
, y
+ height
);
478 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, long x
, long y
)
480 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
481 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
484 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
488 wxCHECK_RET( Ok(), _T("invalid window dc") );
490 wxCHECK_RET( bitmap
.Ok(), _T("invalid bitmap") );
492 /* scale/translate size and position */
494 int xx
= XLOG2DEV(x
);
495 int yy
= YLOG2DEV(y
);
497 int w
= bitmap
.GetWidth();
498 int h
= bitmap
.GetHeight();
500 CalcBoundingBox( x
, y
);
501 CalcBoundingBox( x
+ w
, y
+ h
);
503 if (!m_window
) return;
505 int ww
= XLOG2DEVREL(w
);
506 int hh
= YLOG2DEVREL(h
);
508 /* scale bitmap if required */
512 if ((w
!= ww
) || (h
!= hh
))
514 wxImage
image( bitmap
);
515 image
= image
.Scale( ww
, hh
);
517 use_bitmap
= image
.ConvertToBitmap();
524 /* apply mask if any */
526 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
527 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
531 gdk_gc_set_clip_mask( m_penGC
, mask
);
532 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
535 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
537 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
540 gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 );
544 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
547 gdk_draw_bitmap( m_window
, m_penGC
, bm
, 0, 0, xx
, yy
, -1, -1 );
551 /* remove mask again if any */
555 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
556 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
560 bool wxWindowDC::DoBlit( long xdest
, long ydest
, long width
, long height
,
561 wxDC
*source
, long xsrc
, long ysrc
,
562 int logical_func
, bool useMask
)
564 /* this is the nth try to get this utterly useless function to
565 work. it now completely ignores the scaling or translation
566 of the source dc, but scales correctly on the target dc and
567 knows about possible mask information in a memory dc. */
569 wxCHECK_MSG( Ok(), FALSE
, _T("invalid window dc") );
571 wxCHECK_MSG( source
, FALSE
, _T("invalid source dc") );
573 if (!m_window
) return FALSE
;
575 wxClientDC
*srcDC
= (wxClientDC
*)source
;
576 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
578 bool use_bitmap_method
= FALSE
;
580 if (srcDC
->m_isMemDC
)
582 if (!memDC
->m_selected
.Ok()) return FALSE
;
584 /* we use the "XCopyArea" way to copy a memory dc into
585 y different window if the memory dc BOTH
586 a) doesn't have any mask or its mask isn't used
590 if (useMask
&& (memDC
->m_selected
.GetMask()))
592 /* we HAVE TO use the direct way for memory dcs
593 that have mask since the XCopyArea doesn't know
595 use_bitmap_method
= TRUE
;
597 else if (memDC
->m_selected
.GetDepth() == 1)
599 /* we HAVE TO use the direct way for memory dcs
600 that are bitmaps because XCopyArea doesn't cope
601 with different bit depths */
602 use_bitmap_method
= TRUE
;
604 else if ((xsrc
== 0) && (ysrc
== 0) &&
605 (width
== memDC
->m_selected
.GetWidth()) &&
606 (height
== memDC
->m_selected
.GetHeight()))
608 /* we SHOULD use the direct way if all of the bitmap
609 in the memory dc is copied in which case XCopyArea
610 wouldn't be able able to boost performace by reducing
611 the area to be scaled */
612 use_bitmap_method
= TRUE
;
616 use_bitmap_method
= FALSE
;
620 CalcBoundingBox( xdest
, ydest
);
621 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
623 int old_logical_func
= m_logicalFunction
;
624 SetLogicalFunction( logical_func
);
626 if (use_bitmap_method
)
628 /* scale/translate bitmap size */
630 long bm_width
= memDC
->m_selected
.GetWidth();
631 long bm_height
= memDC
->m_selected
.GetHeight();
633 long bm_ww
= XLOG2DEVREL( bm_width
);
634 long bm_hh
= YLOG2DEVREL( bm_height
);
636 /* scale bitmap if required */
640 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
642 wxImage
image( memDC
->m_selected
);
643 image
= image
.Scale( bm_ww
, bm_hh
);
645 use_bitmap
= image
.ConvertToBitmap();
649 use_bitmap
= memDC
->m_selected
;
652 /* scale/translate size and position */
654 long xx
= XLOG2DEV(xdest
);
655 long yy
= YLOG2DEV(ydest
);
657 long ww
= XLOG2DEVREL(width
);
658 long hh
= YLOG2DEVREL(height
);
660 /* apply mask if any */
662 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
663 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
667 gdk_gc_set_clip_mask( m_penGC
, mask
);
668 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
671 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
673 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
676 gdk_draw_pixmap( m_window
, m_penGC
, pm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
680 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
683 /* we use the textGC here because blitting a bitmap is done
684 using the current text colour */
685 gdk_draw_bitmap( m_window
, m_textGC
, bm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
689 /* remove mask again if any */
693 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
694 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
697 else /* use_bitmap_method */
699 /* scale/translate size and position */
701 long xx
= XLOG2DEV(xdest
);
702 long yy
= YLOG2DEV(ydest
);
704 long ww
= XLOG2DEVREL(width
);
705 long hh
= YLOG2DEVREL(height
);
707 if ((width
!= ww
) || (height
!= hh
))
709 /* draw source window into a bitmap as we cannot scale
710 a window in contrast to a bitmap. this would actually
711 work with memory dcs as well, but we'd lose the mask
712 information and waste one step in this process since
713 a memory already has a bitmap. all this is slightly
714 inefficient as we could take an XImage directly from
715 an X window, but we'd then also have to care that
716 the window is not outside the screen (in which case
717 we'd get a BadMatch or what not).
718 Is a double XGetImage and combined XGetPixel and
719 XPutPixel really faster? I'm not sure. look at wxXt
720 for a different implementation of the same problem. */
722 wxBitmap
bitmap( width
, height
);
723 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
725 xsrc
, ysrc
, width
, height
);
729 wxImage
image( bitmap
);
730 image
= image
.Scale( ww
, hh
);
732 /* convert to bitmap */
734 bitmap
= image
.ConvertToBitmap();
736 /* draw scaled bitmap */
738 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
743 /* no scaling and not a memory dc with a mask either */
745 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
747 xsrc
, ysrc
, width
, height
);
751 SetLogicalFunction( old_logical_func
);
755 void wxWindowDC::DoDrawText( const wxString
&text
, long x
, long y
)
757 wxCHECK_RET( Ok(), _T("invalid window dc") );
759 if (!m_window
) return;
761 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
766 /* CMB 21/5/98: draw text background if mode is wxSOLID */
767 if (m_backgroundMode
== wxSOLID
)
769 long width
= gdk_string_width( font
, text
.mbc_str() );
770 long height
= font
->ascent
+ font
->descent
;
771 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
772 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
773 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
775 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
777 /* CMB 17/7/98: simple underline: ignores scaling and underlying
778 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
779 properties (see wxXt implementation) */
780 if (m_font
.GetUnderlined())
782 long width
= gdk_string_width( font
, text
.mbc_str() );
783 long ul_y
= y
+ font
->ascent
;
784 if (font
->descent
> 0) ul_y
++;
785 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
789 GetTextExtent (text
, &w
, &h
);
790 CalcBoundingBox (x
+ w
, y
+ h
);
791 CalcBoundingBox (x
, y
);
794 void wxWindowDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
795 long *descent
, long *externalLeading
,
796 wxFont
*theFont
) const
798 wxFont fontToUse
= m_font
;
799 if (theFont
) fontToUse
= *theFont
;
801 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
802 if (width
) (*width
) = long(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
803 if (height
) (*height
) = long((font
->ascent
+ font
->descent
) / m_scaleY
);
804 if (descent
) (*descent
) = long(font
->descent
/ m_scaleY
);
805 if (externalLeading
) (*externalLeading
) = 0; // ??
808 long wxWindowDC::GetCharWidth() const
810 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
811 return long(gdk_string_width( font
, "H" ) / m_scaleX
);
814 long wxWindowDC::GetCharHeight() const
816 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
817 return long((font
->ascent
+ font
->descent
) / m_scaleY
);
820 void wxWindowDC::Clear()
822 wxCHECK_RET( Ok(), _T("invalid window dc") );
824 if (!m_window
) return;
826 /* - we either are a memory dc or have a window as the
827 owner. anything else shouldn't happen.
828 - we don't use gdk_window_clear() as we don't set
829 the window's background colour anymore. it is too
830 much pain to keep the DC's and the window's back-
831 ground colour in synch. */
836 m_owner
->GetSize( &width
, &height
);
837 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
844 GetSize( &width
, &height
);
845 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
850 void wxWindowDC::SetFont( const wxFont
&font
)
855 void wxWindowDC::SetPen( const wxPen
&pen
)
857 wxCHECK_RET( Ok(), _T("invalid window dc") );
859 if (m_pen
== pen
) return;
863 if (!m_pen
.Ok()) return;
865 if (!m_window
) return;
867 gint width
= m_pen
.GetWidth();
870 // CMB: if width is non-zero scale it with the dc
875 // X doesn't allow different width in x and y and so we take
877 double w
= 0.5 + (abs(XLOG2DEVREL(width
)) + abs(YLOG2DEVREL(width
))) / 2.0;
881 const static char dotted
[] = {1, 1};
882 const static char short_dashed
[] = {2, 2};
883 const static char long_dashed
[] = {2, 4};
884 const static char dotted_dashed
[] = {3, 3, 1, 3};
886 // We express dash pattern in pen width unit, so we are
887 // independent of zoom factor and so on...
889 const char *req_dash
;
891 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
892 switch (m_pen
.GetStyle())
896 lineStyle
= GDK_LINE_ON_OFF_DASH
;
897 req_nb_dash
= m_pen
.GetDashCount();
898 req_dash
= m_pen
.GetDash();
903 lineStyle
= GDK_LINE_ON_OFF_DASH
;
910 lineStyle
= GDK_LINE_ON_OFF_DASH
;
912 req_dash
= long_dashed
;
917 lineStyle
= GDK_LINE_ON_OFF_DASH
;
919 req_dash
= short_dashed
;
924 // lineStyle = GDK_LINE_DOUBLE_DASH;
925 lineStyle
= GDK_LINE_ON_OFF_DASH
;
927 req_dash
= dotted_dashed
;
936 lineStyle
= GDK_LINE_SOLID
;
937 req_dash
= (wxDash
*)NULL
;
943 #if (GTK_MINOR_VERSION > 0)
944 if (req_dash
&& req_nb_dash
)
946 char *real_req_dash
= new char[req_nb_dash
];
949 for (int i
= 0; i
< req_nb_dash
; i
++)
950 real_req_dash
[i
] = req_dash
[i
] * width
;
951 gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash
);
952 delete[] real_req_dash
;
956 // No Memory. We use non-scaled dash pattern...
957 gdk_gc_set_dashes( m_penGC
, 0, (char*)req_dash
, req_nb_dash
);
962 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
963 switch (m_pen
.GetCap())
965 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
966 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
967 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
970 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
971 switch (m_pen
.GetJoin())
973 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
974 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
975 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
978 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
980 m_pen
.GetColour().CalcPixel( m_cmap
);
981 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
984 void wxWindowDC::SetBrush( const wxBrush
&brush
)
986 wxCHECK_RET( Ok(), _T("invalid window dc") );
988 if (m_brush
== brush
) return;
992 if (!m_brush
.Ok()) return;
994 if (!m_window
) return;
996 m_brush
.GetColour().CalcPixel( m_cmap
);
997 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
999 gdk_gc_set_fill( m_brushGC
, GDK_SOLID
);
1001 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
1003 if (m_brush
.GetStipple()->GetPixmap())
1005 gdk_gc_set_fill( m_brushGC
, GDK_TILED
);
1006 gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
1010 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1011 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
1015 if (IS_HATCH(m_brush
.GetStyle()))
1017 gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED
);
1018 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
1019 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
1023 void wxWindowDC::SetBackground( const wxBrush
&brush
)
1025 /* CMB 21/7/98: Added SetBackground. Sets background brush
1026 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1028 wxCHECK_RET( Ok(), _T("invalid window dc") );
1030 if (m_backgroundBrush
== brush
) return;
1032 m_backgroundBrush
= brush
;
1034 if (!m_backgroundBrush
.Ok()) return;
1036 if (!m_window
) return;
1038 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1039 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1040 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1041 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1042 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1044 gdk_gc_set_fill( m_bgGC
, GDK_SOLID
);
1046 if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok()))
1048 if (m_backgroundBrush
.GetStipple()->GetPixmap())
1050 gdk_gc_set_fill( m_bgGC
, GDK_TILED
);
1051 gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1055 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1056 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() );
1060 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1062 gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED
);
1063 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1064 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1068 void wxWindowDC::SetLogicalFunction( int function
)
1070 wxCHECK_RET( Ok(), _T("invalid window dc") );
1072 if (m_logicalFunction
== function
) return;
1074 GdkFunction mode
= GDK_COPY
;
1077 case wxXOR
: mode
= GDK_XOR
; break;
1078 case wxINVERT
: mode
= GDK_INVERT
; break;
1079 #if (GTK_MINOR_VERSION > 0)
1080 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1081 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1082 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1083 case wxSET
: mode
= GDK_SET
; break;
1084 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1086 case wxAND
: mode
= GDK_AND
; break;
1088 case wxOR
: mode
= GDK_OR
; break;
1089 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1090 case wxNAND
: mode
= GDK_NAND
; break;
1091 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1092 case wxCOPY
: mode
= GDK_COPY
; break;
1093 case wxNO_OP
: mode
= GDK_NOOP
; break;
1094 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1098 wxFAIL_MSG( _T("unsupported logical function") );
1103 m_logicalFunction
= function
;
1105 if (!m_window
) return;
1107 gdk_gc_set_function( m_penGC
, mode
);
1108 gdk_gc_set_function( m_brushGC
, mode
);
1109 gdk_gc_set_function( m_textGC
, mode
);
1112 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1114 wxCHECK_RET( Ok(), _T("invalid window dc") );
1116 if (m_textForegroundColour
== col
) return;
1118 m_textForegroundColour
= col
;
1119 if (!m_textForegroundColour
.Ok()) return;
1121 if (!m_window
) return;
1123 m_textForegroundColour
.CalcPixel( m_cmap
);
1124 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1127 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1129 wxCHECK_RET( Ok(), _T("invalid window dc") );
1131 if (m_textBackgroundColour
== col
) return;
1133 m_textBackgroundColour
= col
;
1134 if (!m_textBackgroundColour
.Ok()) return;
1136 if (!m_window
) return;
1138 m_textBackgroundColour
.CalcPixel( m_cmap
);
1139 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1142 void wxWindowDC::SetBackgroundMode( int mode
)
1144 wxCHECK_RET( Ok(), _T("invalid window dc") );
1146 m_backgroundMode
= mode
;
1148 if (!m_window
) return;
1150 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1151 // transparent/solid background mode
1153 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1155 gdk_gc_set_fill( m_brushGC
,
1156 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1160 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1162 wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") );
1165 void wxWindowDC::DoSetClippingRegion( long x
, long y
, long width
, long height
)
1167 wxCHECK_RET( Ok(), _T("invalid window dc") );
1169 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1171 if (!m_window
) return;
1174 rect
.x
= XLOG2DEV(x
);
1175 rect
.y
= YLOG2DEV(y
);
1176 rect
.width
= XLOG2DEVREL(width
);
1177 rect
.height
= YLOG2DEVREL(height
);
1178 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1179 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1180 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1181 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1184 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1186 wxCHECK_RET( Ok(), _T("invalid window dc") );
1190 DestroyClippingRegion();
1194 if (!m_window
) return;
1196 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1197 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1198 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1199 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1202 void wxWindowDC::DestroyClippingRegion()
1204 wxCHECK_RET( Ok(), _T("invalid window dc") );
1206 wxDC::DestroyClippingRegion();
1208 if (!m_window
) return;
1210 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1211 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1212 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1213 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1216 void wxWindowDC::SetUpDC()
1220 m_logicalFunction
= wxCOPY
;
1221 m_penGC
= gdk_gc_new( m_window
);
1222 m_brushGC
= gdk_gc_new( m_window
);
1223 m_textGC
= gdk_gc_new( m_window
);
1224 m_bgGC
= gdk_gc_new( m_window
);
1226 wxColour
tmp_col( m_textForegroundColour
);
1227 m_textForegroundColour
= wxNullColour
;
1228 SetTextForeground( tmp_col
);
1229 tmp_col
= m_textBackgroundColour
;
1230 m_textBackgroundColour
= wxNullColour
;
1231 SetTextBackground( tmp_col
);
1233 wxPen
tmp_pen( m_pen
);
1237 wxFont
tmp_font( m_font
);
1238 m_font
= wxNullFont
;
1239 SetFont( tmp_font
);
1241 wxBrush
tmp_brush( m_brush
);
1242 m_brush
= wxNullBrush
;
1243 SetBrush( tmp_brush
);
1246 tmp_brush = m_backgroundBrush;
1247 m_backgroundBrush = wxNullBrush;
1248 SetBackground( tmp_brush );
1250 tmp_brush
= m_backgroundBrush
;
1251 m_backgroundBrush
= wxNullBrush
;
1252 SetBackground( *wxWHITE_BRUSH
);
1253 m_backgroundBrush
= tmp_brush
;
1257 hatch_bitmap
= hatches
;
1258 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1259 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1260 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1261 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1262 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1263 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1267 void wxWindowDC::Destroy()
1269 if (m_penGC
) gdk_gc_unref( m_penGC
);
1270 m_penGC
= (GdkGC
*) NULL
;
1271 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1272 m_brushGC
= (GdkGC
*) NULL
;
1273 if (m_textGC
) gdk_gc_unref( m_textGC
);
1274 m_textGC
= (GdkGC
*) NULL
;
1275 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1276 m_bgGC
= (GdkGC
*) NULL
;
1279 void wxWindowDC::ComputeScaleAndOrigin()
1281 /* CMB: copy scale to see if it changes */
1282 double origScaleX
= m_scaleX
;
1283 double origScaleY
= m_scaleY
;
1285 wxDC::ComputeScaleAndOrigin();
1287 /* CMB: if scale has changed call SetPen to recalulate the line width */
1288 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1291 /* this is a bit artificial, but we need to force wxDC to think
1292 the pen has changed */
1299 // Resolution in pixels per logical inch
1300 wxSize
wxWindowDC::GetPPI() const
1302 return wxSize(100, 100);
1305 int wxWindowDC::GetDepth() const
1307 wxFAIL_MSG(_T("not implemented"));
1313 // ----------------------------------- spline code ----------------------------------------
1315 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1316 double a3
, double b3
, double a4
, double b4
);
1317 void wx_clear_stack();
1318 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1319 double *y3
, double *x4
, double *y4
);
1320 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1321 double x4
, double y4
);
1322 static bool wx_spline_add_point(double x
, double y
);
1323 static void wx_spline_draw_point_array(wxDC
*dc
);
1325 wxList wx_spline_point_list
;
1327 #define half(z1, z2) ((z1+z2)/2.0)
1330 /* iterative version */
1332 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1335 register double xmid
, ymid
;
1336 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1339 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1341 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1342 xmid
= (double)half(x2
, x3
);
1343 ymid
= (double)half(y2
, y3
);
1344 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1345 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1346 wx_spline_add_point( x1
, y1
);
1347 wx_spline_add_point( xmid
, ymid
);
1349 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1350 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1351 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1352 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1357 /* utilities used by spline drawing routines */
1359 typedef struct wx_spline_stack_struct
{
1360 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1363 #define SPLINE_STACK_DEPTH 20
1364 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1365 static Stack
*wx_stack_top
;
1366 static int wx_stack_count
;
1368 void wx_clear_stack()
1370 wx_stack_top
= wx_spline_stack
;
1374 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1376 wx_stack_top
->x1
= x1
;
1377 wx_stack_top
->y1
= y1
;
1378 wx_stack_top
->x2
= x2
;
1379 wx_stack_top
->y2
= y2
;
1380 wx_stack_top
->x3
= x3
;
1381 wx_stack_top
->y3
= y3
;
1382 wx_stack_top
->x4
= x4
;
1383 wx_stack_top
->y4
= y4
;
1388 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1389 double *x3
, double *y3
, double *x4
, double *y4
)
1391 if (wx_stack_count
== 0)
1395 *x1
= wx_stack_top
->x1
;
1396 *y1
= wx_stack_top
->y1
;
1397 *x2
= wx_stack_top
->x2
;
1398 *y2
= wx_stack_top
->y2
;
1399 *x3
= wx_stack_top
->x3
;
1400 *y3
= wx_stack_top
->y3
;
1401 *x4
= wx_stack_top
->x4
;
1402 *y4
= wx_stack_top
->y4
;
1406 static bool wx_spline_add_point(double x
, double y
)
1408 wxPoint
*point
= new wxPoint
;
1411 wx_spline_point_list
.Append((wxObject
*)point
);
1415 static void wx_spline_draw_point_array(wxDC
*dc
)
1417 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1418 wxNode
*node
= wx_spline_point_list
.First();
1421 wxPoint
*point
= (wxPoint
*)node
->Data();
1424 node
= wx_spline_point_list
.First();
1428 void wxWindowDC::DoDrawSpline( wxList
*points
)
1430 wxCHECK_RET( Ok(), _T("invalid window dc") );
1433 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1434 double x1
, y1
, x2
, y2
;
1436 wxNode
*node
= points
->First();
1437 p
= (wxPoint
*)node
->Data();
1442 node
= node
->Next();
1443 p
= (wxPoint
*)node
->Data();
1447 cx1
= (double)((x1
+ x2
) / 2);
1448 cy1
= (double)((y1
+ y2
) / 2);
1449 cx2
= (double)((cx1
+ x2
) / 2);
1450 cy2
= (double)((cy1
+ y2
) / 2);
1452 wx_spline_add_point(x1
, y1
);
1454 while ((node
= node
->Next()) != NULL
)
1456 p
= (wxPoint
*)node
->Data();
1461 cx4
= (double)(x1
+ x2
) / 2;
1462 cy4
= (double)(y1
+ y2
) / 2;
1463 cx3
= (double)(x1
+ cx4
) / 2;
1464 cy3
= (double)(y1
+ cy4
) / 2;
1466 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1470 cx2
= (double)(cx1
+ x2
) / 2;
1471 cy2
= (double)(cy1
+ y2
) / 2;
1474 wx_spline_add_point( cx1
, cy1
);
1475 wx_spline_add_point( x2
, y2
);
1477 wx_spline_draw_point_array( this );
1480 #endif // wxUSE_SPLINE
1482 //-----------------------------------------------------------------------------
1484 //-----------------------------------------------------------------------------
1486 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1488 wxPaintDC::wxPaintDC()
1493 wxPaintDC::wxPaintDC( wxWindow
*win
)
1498 //-----------------------------------------------------------------------------
1500 //-----------------------------------------------------------------------------
1502 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1504 wxClientDC::wxClientDC()
1509 wxClientDC::wxClientDC( wxWindow
*win
)