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
;
114 wxASSERT_MSG( window
, _T("DC needs a window") );
116 GtkWidget
*widget
= window
->m_wxwindow
;
118 wxASSERT_MSG( widget
, _T("DC needs a widget") );
120 m_window
= widget
->window
;
125 /* don't report problems */
131 if (window
->m_wxwindow
)
132 m_cmap
= gtk_widget_get_colormap( window
->m_wxwindow
);
134 m_cmap
= gtk_widget_get_colormap( window
->m_widget
);
138 /* this must be done after SetUpDC, bacause SetUpDC calls the
139 repective SetBrush, SetPen, SetBackground etc functions
140 to set up the DC. SetBackground call m_owner->SetBackground
141 and this might not be desired as the standard dc background
142 is white whereas a window might assume gray to be the
143 standard (as e.g. wxStatusBar) */
148 wxWindowDC::~wxWindowDC()
153 void wxWindowDC::DoFloodFill( long WXUNUSED(x
), long WXUNUSED(y
),
154 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
156 wxFAIL_MSG( _T("wxWindowDC::DoFloodFill not implemented") );
159 bool wxWindowDC::DoGetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
161 wxFAIL_MSG( _T("wxWindowDC::DoGetPixel not implemented") );
165 void wxWindowDC::DoDrawLine( long x1
, long y1
, long x2
, long y2
)
167 wxCHECK_RET( Ok(), _T("invalid window dc") );
169 if (m_pen
.GetStyle() != wxTRANSPARENT
)
172 gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
174 CalcBoundingBox(x1
, y1
);
175 CalcBoundingBox(x2
, y2
);
179 void wxWindowDC::DoCrossHair( long x
, long y
)
181 wxCHECK_RET( Ok(), _T("invalid window dc") );
183 if (m_pen
.GetStyle() != wxTRANSPARENT
)
188 long xx
= XLOG2DEV(x
);
189 long yy
= YLOG2DEV(y
);
192 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
193 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
198 void wxWindowDC::DoDrawArc( long x1
, long y1
, long x2
, long y2
,
201 wxCHECK_RET( Ok(), _T("invalid window dc") );
203 long xx1
= XLOG2DEV(x1
);
204 long yy1
= YLOG2DEV(y1
);
205 long xx2
= XLOG2DEV(x2
);
206 long yy2
= YLOG2DEV(y2
);
207 long xxc
= XLOG2DEV(xc
);
208 long yyc
= YLOG2DEV(yc
);
209 double dx
= xx1
- xxc
;
210 double dy
= yy1
- yyc
;
211 double radius
= sqrt(dx
*dx
+dy
*dy
);
212 long r
= (long)radius
;
213 double radius1
, radius2
;
215 if (xx1
== xx2
&& yy1
== yy2
)
223 radius1
= radius2
= 0.0;
227 radius1
= (xx1
- xxc
== 0) ?
228 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
229 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
230 radius2
= (xx2
- xxc
== 0) ?
231 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
232 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
234 long alpha1
= long(radius1
* 64.0);
235 long alpha2
= long((radius2
- radius1
) * 64.0);
236 while (alpha2
<= 0) alpha2
+= 360*64;
237 while (alpha1
> 360*64) alpha1
-= 360*64;
241 if (m_brush
.GetStyle() != wxTRANSPARENT
)
242 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
244 if (m_pen
.GetStyle() != wxTRANSPARENT
)
245 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
248 CalcBoundingBox (x1
, y1
);
249 CalcBoundingBox (x2
, y2
);
252 void wxWindowDC::DoDrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
254 wxCHECK_RET( Ok(), _T("invalid window dc") );
256 long xx
= XLOG2DEV(x
);
257 long yy
= YLOG2DEV(y
);
258 long ww
= m_signX
* XLOG2DEVREL(width
);
259 long hh
= m_signY
* YLOG2DEVREL(height
);
261 // CMB: handle -ve width and/or height
262 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
263 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
267 long start
= long(sa
* 64.0);
268 long end
= long(ea
* 64.0);
270 if (m_brush
.GetStyle() != wxTRANSPARENT
)
271 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
273 if (m_pen
.GetStyle() != wxTRANSPARENT
)
274 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
277 CalcBoundingBox (x
, y
);
278 CalcBoundingBox (x
+ width
, y
+ height
);
281 void wxWindowDC::DoDrawPoint( long x
, long y
)
283 wxCHECK_RET( Ok(), _T("invalid window dc") );
285 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
286 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
288 CalcBoundingBox (x
, y
);
291 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
293 wxCHECK_RET( Ok(), _T("invalid window dc") );
295 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
298 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
300 for (int i
= 0; i
< n
-1; i
++)
302 long x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
303 long x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
304 long y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
305 long y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
307 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
309 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
313 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
) )
315 wxCHECK_RET( Ok(), _T("invalid window dc") );
319 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
321 for (i
= 0 ; i
< n
; i
++)
323 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
324 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
326 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
329 if (m_brush
.GetStyle() != wxTRANSPARENT
)
330 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
334 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
336 for (i
= 0 ; i
< n
; i
++)
338 gdk_draw_line( m_window
, m_penGC
,
341 gdkpoints
[(i
+1)%n
].x
,
342 gdkpoints
[(i
+1)%n
].y
);
349 void wxWindowDC::DoDrawRectangle( long x
, long y
, long width
, long height
)
351 wxCHECK_RET( Ok(), _T("invalid window dc") );
353 long xx
= XLOG2DEV(x
);
354 long yy
= YLOG2DEV(y
);
355 long ww
= m_signX
* XLOG2DEVREL(width
);
356 long hh
= m_signY
* YLOG2DEVREL(height
);
358 // CMB: draw nothing if transformed w or h is 0
359 if (ww
== 0 || hh
== 0) return;
361 // CMB: handle -ve width and/or height
362 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
363 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
367 if (m_brush
.GetStyle() != wxTRANSPARENT
)
368 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
370 if (m_pen
.GetStyle() != wxTRANSPARENT
)
371 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
374 CalcBoundingBox( x
, y
);
375 CalcBoundingBox( x
+ width
, y
+ height
);
378 void wxWindowDC::DoDrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
380 wxCHECK_RET( Ok(), _T("invalid window dc") );
382 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
384 long xx
= XLOG2DEV(x
);
385 long yy
= YLOG2DEV(y
);
386 long ww
= m_signX
* XLOG2DEVREL(width
);
387 long hh
= m_signY
* YLOG2DEVREL(height
);
388 long rr
= XLOG2DEVREL((long)radius
);
390 // CMB: handle -ve width and/or height
391 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
392 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
394 // CMB: if radius is zero use DrawRectangle() instead to avoid
395 // X drawing errors with small radii
398 DrawRectangle( x
, y
, width
, height
);
402 // CMB: draw nothing if transformed w or h is 0
403 if (ww
== 0 || hh
== 0) return;
405 // CMB: adjust size if outline is drawn otherwise the result is
406 // 1 pixel too wide and high
407 if (m_pen
.GetStyle() != wxTRANSPARENT
)
415 // CMB: ensure dd is not larger than rectangle otherwise we
416 // get an hour glass shape
418 if (dd
> ww
) dd
= ww
;
419 if (dd
> hh
) dd
= hh
;
422 if (m_brush
.GetStyle() != wxTRANSPARENT
)
424 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
425 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
426 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
427 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
428 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
429 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
432 if (m_pen
.GetStyle() != wxTRANSPARENT
)
434 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
435 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
436 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
437 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
438 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
439 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
440 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
441 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
445 // this ignores the radius
446 CalcBoundingBox( x
, y
);
447 CalcBoundingBox( x
+ width
, y
+ height
);
450 void wxWindowDC::DoDrawEllipse( long x
, long y
, long width
, long height
)
452 wxCHECK_RET( Ok(), _T("invalid window dc") );
454 long xx
= XLOG2DEV(x
);
455 long yy
= YLOG2DEV(y
);
456 long ww
= m_signX
* XLOG2DEVREL(width
);
457 long hh
= m_signY
* YLOG2DEVREL(height
);
459 // CMB: handle -ve width and/or height
460 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
461 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
465 if (m_brush
.GetStyle() != wxTRANSPARENT
)
466 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
468 if (m_pen
.GetStyle() != wxTRANSPARENT
)
469 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
472 CalcBoundingBox( x
- width
, y
- height
);
473 CalcBoundingBox( x
+ width
, y
+ height
);
476 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, long x
, long y
)
478 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
479 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
482 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
486 wxCHECK_RET( Ok(), _T("invalid window dc") );
488 wxCHECK_RET( bitmap
.Ok(), _T("invalid bitmap") );
490 /* scale/translate size and position */
492 int xx
= XLOG2DEV(x
);
493 int yy
= YLOG2DEV(y
);
495 int w
= bitmap
.GetWidth();
496 int h
= bitmap
.GetHeight();
498 CalcBoundingBox( x
, y
);
499 CalcBoundingBox( x
+ w
, y
+ h
);
501 if (!m_window
) return;
503 int ww
= XLOG2DEVREL(w
);
504 int hh
= YLOG2DEVREL(h
);
506 /* scale bitmap if required */
510 if ((w
!= ww
) || (h
!= hh
))
512 wxImage
image( bitmap
);
513 image
= image
.Scale( ww
, hh
);
515 use_bitmap
= image
.ConvertToBitmap();
522 /* apply mask if any */
524 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
525 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
529 gdk_gc_set_clip_mask( m_penGC
, mask
);
530 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
533 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
535 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
538 gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 );
542 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
545 gdk_draw_bitmap( m_window
, m_penGC
, bm
, 0, 0, xx
, yy
, -1, -1 );
549 /* remove mask again if any */
553 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
554 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
558 bool wxWindowDC::DoBlit( long xdest
, long ydest
, long width
, long height
,
559 wxDC
*source
, long xsrc
, long ysrc
,
560 int logical_func
, bool useMask
)
562 /* this is the nth try to get this utterly useless function to
563 work. it now completely ignores the scaling or translation
564 of the source dc, but scales correctly on the target dc and
565 knows about possible mask information in a memory dc. */
567 wxCHECK_MSG( Ok(), FALSE
, _T("invalid window dc") );
569 wxCHECK_MSG( source
, FALSE
, _T("invalid source dc") );
571 if (!m_window
) return FALSE
;
573 wxClientDC
*srcDC
= (wxClientDC
*)source
;
574 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
576 bool use_bitmap_method
= FALSE
;
578 if (srcDC
->m_isMemDC
)
580 if (!memDC
->m_selected
.Ok()) return FALSE
;
582 /* we use the "XCopyArea" way to copy a memory dc into
583 y different window if the memory dc BOTH
584 a) doesn't have any mask or its mask isn't used
588 if (useMask
&& (memDC
->m_selected
.GetMask()))
590 /* we HAVE TO use the direct way for memory dcs
591 that have mask since the XCopyArea doesn't know
593 use_bitmap_method
= TRUE
;
595 else if (memDC
->m_selected
.GetDepth() == 1)
597 /* we HAVE TO use the direct way for memory dcs
598 that are bitmaps because XCopyArea doesn't cope
599 with different bit depths */
600 use_bitmap_method
= TRUE
;
602 else if ((xsrc
== 0) && (ysrc
== 0) &&
603 (width
== memDC
->m_selected
.GetWidth()) &&
604 (height
== memDC
->m_selected
.GetHeight()))
606 /* we SHOULD use the direct way if all of the bitmap
607 in the memory dc is copied in which case XCopyArea
608 wouldn't be able able to boost performace by reducing
609 the area to be scaled */
610 use_bitmap_method
= TRUE
;
614 use_bitmap_method
= FALSE
;
618 CalcBoundingBox( xdest
, ydest
);
619 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
621 int old_logical_func
= m_logicalFunction
;
622 SetLogicalFunction( logical_func
);
624 if (use_bitmap_method
)
626 /* scale/translate bitmap size */
628 long bm_width
= memDC
->m_selected
.GetWidth();
629 long bm_height
= memDC
->m_selected
.GetHeight();
631 long bm_ww
= XLOG2DEVREL( bm_width
);
632 long bm_hh
= YLOG2DEVREL( bm_height
);
634 /* scale bitmap if required */
638 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
640 wxImage
image( memDC
->m_selected
);
641 image
= image
.Scale( bm_ww
, bm_hh
);
643 use_bitmap
= image
.ConvertToBitmap();
647 use_bitmap
= memDC
->m_selected
;
650 /* scale/translate size and position */
652 long xx
= XLOG2DEV(xdest
);
653 long yy
= YLOG2DEV(ydest
);
655 long ww
= XLOG2DEVREL(width
);
656 long hh
= YLOG2DEVREL(height
);
658 /* apply mask if any */
660 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
661 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
665 gdk_gc_set_clip_mask( m_penGC
, mask
);
666 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
669 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
671 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
674 gdk_draw_pixmap( m_window
, m_penGC
, pm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
678 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
681 /* we use the textGC here because blitting a bitmap is done
682 using the current text colour */
683 gdk_draw_bitmap( m_window
, m_textGC
, bm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
687 /* remove mask again if any */
691 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
692 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
695 else /* use_bitmap_method */
697 /* scale/translate size and position */
699 long xx
= XLOG2DEV(xdest
);
700 long yy
= YLOG2DEV(ydest
);
702 long ww
= XLOG2DEVREL(width
);
703 long hh
= YLOG2DEVREL(height
);
705 if ((width
!= ww
) || (height
!= hh
))
707 /* draw source window into a bitmap as we cannot scale
708 a window in contrast to a bitmap. this would actually
709 work with memory dcs as well, but we'd lose the mask
710 information and waste one step in this process since
711 a memory already has a bitmap. all this is slightly
712 inefficient as we could take an XImage directly from
713 an X window, but we'd then also have to care that
714 the window is not outside the screen (in which case
715 we'd get a BadMatch or what not).
716 Is a double XGetImage and combined XGetPixel and
717 XPutPixel really faster? I'm not sure. look at wxXt
718 for a different implementation of the same problem. */
720 wxBitmap
bitmap( width
, height
);
721 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
723 xsrc
, ysrc
, width
, height
);
727 wxImage
image( bitmap
);
728 image
= image
.Scale( ww
, hh
);
730 /* convert to bitmap */
732 bitmap
= image
.ConvertToBitmap();
734 /* draw scaled bitmap */
736 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
741 /* no scaling and not a memory dc with a mask either */
743 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
745 xsrc
, ysrc
, width
, height
);
749 SetLogicalFunction( old_logical_func
);
753 void wxWindowDC::DoDrawText( const wxString
&text
, long x
, long y
)
755 wxCHECK_RET( Ok(), _T("invalid window dc") );
757 if (!m_window
) return;
759 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
764 /* CMB 21/5/98: draw text background if mode is wxSOLID */
765 if (m_backgroundMode
== wxSOLID
)
767 long width
= gdk_string_width( font
, text
.mbc_str() );
768 long height
= font
->ascent
+ font
->descent
;
769 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
770 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
771 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
773 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
775 /* CMB 17/7/98: simple underline: ignores scaling and underlying
776 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
777 properties (see wxXt implementation) */
778 if (m_font
.GetUnderlined())
780 long width
= gdk_string_width( font
, text
.mbc_str() );
781 long ul_y
= y
+ font
->ascent
;
782 if (font
->descent
> 0) ul_y
++;
783 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
787 GetTextExtent (text
, &w
, &h
);
788 CalcBoundingBox (x
+ w
, y
+ h
);
789 CalcBoundingBox (x
, y
);
792 void wxWindowDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
793 long *descent
, long *externalLeading
,
794 wxFont
*theFont
) const
796 wxFont fontToUse
= m_font
;
797 if (theFont
) fontToUse
= *theFont
;
799 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
800 if (width
) (*width
) = long(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
801 if (height
) (*height
) = long((font
->ascent
+ font
->descent
) / m_scaleY
);
802 if (descent
) (*descent
) = long(font
->descent
/ m_scaleY
);
803 if (externalLeading
) (*externalLeading
) = 0; // ??
806 long wxWindowDC::GetCharWidth() const
808 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
809 return long(gdk_string_width( font
, "H" ) / m_scaleX
);
812 long wxWindowDC::GetCharHeight() const
814 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
815 return long((font
->ascent
+ font
->descent
) / m_scaleY
);
818 void wxWindowDC::Clear()
820 wxCHECK_RET( Ok(), _T("invalid window dc") );
822 if (!m_window
) return;
824 /* - we either are a memory dc or have a window as the
825 owner. anything else shouldn't happen.
826 - we don't use gdk_window_clear() as we don't set
827 the window's background colour anymore. it is too
828 much pain to keep the DC's and the window's back-
829 ground colour in synch. */
834 m_owner
->GetSize( &width
, &height
);
835 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
842 GetSize( &width
, &height
);
843 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
848 void wxWindowDC::SetFont( const wxFont
&font
)
853 void wxWindowDC::SetPen( const wxPen
&pen
)
855 wxCHECK_RET( Ok(), _T("invalid window dc") );
857 if (m_pen
== pen
) return;
861 if (!m_pen
.Ok()) return;
863 if (!m_window
) return;
865 gint width
= m_pen
.GetWidth();
866 // CMB: if width is non-zero scale it with the dc
873 // X doesn't allow different width in x and y and so we take
875 double w
= 0.5 + (abs(XLOG2DEVREL(width
)) + abs(YLOG2DEVREL(width
))) / 2.0;
879 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
880 switch (m_pen
.GetStyle())
882 case wxSOLID
: { lineStyle
= GDK_LINE_SOLID
; break; }
883 case wxDOT
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
884 case wxLONG_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
885 case wxSHORT_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
886 case wxDOT_DASH
: { lineStyle
= GDK_LINE_DOUBLE_DASH
; break; }
889 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
890 switch (m_pen
.GetCap())
892 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
893 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
894 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
897 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
898 switch (m_pen
.GetJoin())
900 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
901 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
902 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
905 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
907 m_pen
.GetColour().CalcPixel( m_cmap
);
908 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
911 void wxWindowDC::SetBrush( const wxBrush
&brush
)
913 wxCHECK_RET( Ok(), _T("invalid window dc") );
915 if (m_brush
== brush
) return;
919 if (!m_brush
.Ok()) return;
921 if (!m_window
) return;
923 m_brush
.GetColour().CalcPixel( m_cmap
);
924 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
926 GdkFill fillStyle
= GDK_SOLID
;
927 switch (m_brush
.GetStyle())
933 fillStyle
= GDK_STIPPLED
;
936 gdk_gc_set_fill( m_brushGC
, fillStyle
);
938 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
940 if (m_brush
.GetStipple()->GetPixmap())
941 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
943 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
946 if (IS_HATCH(m_brush
.GetStyle()))
948 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
949 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
953 void wxWindowDC::SetBackground( const wxBrush
&brush
)
955 /* CMB 21/7/98: Added SetBackground. Sets background brush
956 * for Clear() and bg colour for shapes filled with cross-hatch brush */
958 wxCHECK_RET( Ok(), _T("invalid window dc") );
960 if (m_backgroundBrush
== brush
) return;
962 m_backgroundBrush
= brush
;
964 if (!m_backgroundBrush
.Ok()) return;
966 if (!m_window
) return;
968 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
969 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
970 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
971 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
972 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
974 GdkFill fillStyle
= GDK_SOLID
;
975 switch (m_backgroundBrush
.GetStyle())
981 fillStyle
= GDK_STIPPLED
;
984 gdk_gc_set_fill( m_bgGC
, fillStyle
);
986 if (m_backgroundBrush
.GetStyle() == wxSTIPPLE
)
988 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
991 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
993 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
994 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
998 void wxWindowDC::SetLogicalFunction( int function
)
1000 wxCHECK_RET( Ok(), _T("invalid window dc") );
1002 if (m_logicalFunction
== function
) return;
1004 GdkFunction mode
= GDK_COPY
;
1007 case wxXOR
: mode
= GDK_XOR
; break;
1008 case wxINVERT
: mode
= GDK_INVERT
; break;
1009 #if (GTK_MINOR_VERSION > 0)
1010 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1011 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1012 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1013 case wxSET
: mode
= GDK_SET
; break;
1014 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1016 case wxAND
: mode
= GDK_AND
; break;
1018 case wxOR
: mode
= GDK_OR
; break;
1019 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1020 case wxNAND
: mode
= GDK_NAND
; break;
1021 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1022 case wxCOPY
: mode
= GDK_COPY
; break;
1023 case wxNO_OP
: mode
= GDK_NOOP
; break;
1024 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1028 wxFAIL_MSG( _T("unsupported logical function") );
1033 m_logicalFunction
= function
;
1035 if (!m_window
) return;
1037 gdk_gc_set_function( m_penGC
, mode
);
1038 gdk_gc_set_function( m_brushGC
, mode
);
1039 gdk_gc_set_function( m_textGC
, mode
);
1042 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1044 wxCHECK_RET( Ok(), _T("invalid window dc") );
1046 if (m_textForegroundColour
== col
) return;
1048 m_textForegroundColour
= col
;
1049 if (!m_textForegroundColour
.Ok()) return;
1051 if (!m_window
) return;
1053 m_textForegroundColour
.CalcPixel( m_cmap
);
1054 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1057 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1059 wxCHECK_RET( Ok(), _T("invalid window dc") );
1061 if (m_textBackgroundColour
== col
) return;
1063 m_textBackgroundColour
= col
;
1064 if (!m_textBackgroundColour
.Ok()) return;
1066 if (!m_window
) return;
1068 m_textBackgroundColour
.CalcPixel( m_cmap
);
1069 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1072 void wxWindowDC::SetBackgroundMode( int mode
)
1074 wxCHECK_RET( Ok(), _T("invalid window dc") );
1076 m_backgroundMode
= mode
;
1078 if (!m_window
) return;
1080 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1081 // transparent/solid background mode
1083 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1085 gdk_gc_set_fill( m_brushGC
,
1086 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1090 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1092 wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") );
1095 void wxWindowDC::DoSetClippingRegion( long x
, long y
, long width
, long height
)
1097 wxCHECK_RET( Ok(), _T("invalid window dc") );
1099 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1101 if (!m_window
) return;
1104 rect
.x
= XLOG2DEV(x
);
1105 rect
.y
= YLOG2DEV(y
);
1106 rect
.width
= XLOG2DEVREL(width
);
1107 rect
.height
= YLOG2DEVREL(height
);
1108 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1109 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1110 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1111 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1114 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1116 wxCHECK_RET( Ok(), _T("invalid window dc") );
1120 DestroyClippingRegion();
1124 if (!m_window
) return;
1126 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1127 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1128 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1129 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1132 void wxWindowDC::DestroyClippingRegion()
1134 wxCHECK_RET( Ok(), _T("invalid window dc") );
1136 wxDC::DestroyClippingRegion();
1138 if (!m_window
) return;
1140 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1141 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1142 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1143 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1146 void wxWindowDC::SetUpDC()
1150 m_logicalFunction
= wxCOPY
;
1151 m_penGC
= gdk_gc_new( m_window
);
1152 m_brushGC
= gdk_gc_new( m_window
);
1153 m_textGC
= gdk_gc_new( m_window
);
1154 m_bgGC
= gdk_gc_new( m_window
);
1156 wxColour
tmp_col( m_textForegroundColour
);
1157 m_textForegroundColour
= wxNullColour
;
1158 SetTextForeground( tmp_col
);
1159 tmp_col
= m_textBackgroundColour
;
1160 m_textBackgroundColour
= wxNullColour
;
1161 SetTextBackground( tmp_col
);
1163 wxPen
tmp_pen( m_pen
);
1167 wxFont
tmp_font( m_font
);
1168 m_font
= wxNullFont
;
1169 SetFont( tmp_font
);
1171 wxBrush
tmp_brush( m_brush
);
1172 m_brush
= wxNullBrush
;
1173 SetBrush( tmp_brush
);
1176 tmp_brush = m_backgroundBrush;
1177 m_backgroundBrush = wxNullBrush;
1178 SetBackground( tmp_brush );
1180 tmp_brush
= m_backgroundBrush
;
1181 m_backgroundBrush
= wxNullBrush
;
1182 SetBackground( *wxWHITE_BRUSH
);
1183 m_backgroundBrush
= tmp_brush
;
1187 hatch_bitmap
= hatches
;
1188 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1189 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1190 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1191 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1192 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1193 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1197 void wxWindowDC::Destroy()
1199 if (m_penGC
) gdk_gc_unref( m_penGC
);
1200 m_penGC
= (GdkGC
*) NULL
;
1201 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1202 m_brushGC
= (GdkGC
*) NULL
;
1203 if (m_textGC
) gdk_gc_unref( m_textGC
);
1204 m_textGC
= (GdkGC
*) NULL
;
1205 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1206 m_bgGC
= (GdkGC
*) NULL
;
1209 void wxWindowDC::ComputeScaleAndOrigin()
1211 /* CMB: copy scale to see if it changes */
1212 double origScaleX
= m_scaleX
;
1213 double origScaleY
= m_scaleY
;
1215 wxDC::ComputeScaleAndOrigin();
1217 /* CMB: if scale has changed call SetPen to recalulate the line width */
1218 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1221 /* this is a bit artificial, but we need to force wxDC to think
1222 the pen has changed */
1229 // Resolution in pixels per logical inch
1230 wxSize
wxWindowDC::GetPPI() const
1232 return wxSize(100, 100);
1235 int wxWindowDC::GetDepth() const
1237 wxFAIL_MSG(_T("not implemented"));
1243 // ----------------------------------- spline code ----------------------------------------
1245 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1246 double a3
, double b3
, double a4
, double b4
);
1247 void wx_clear_stack();
1248 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1249 double *y3
, double *x4
, double *y4
);
1250 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1251 double x4
, double y4
);
1252 static bool wx_spline_add_point(double x
, double y
);
1253 static void wx_spline_draw_point_array(wxDC
*dc
);
1255 wxList wx_spline_point_list
;
1257 #define half(z1, z2) ((z1+z2)/2.0)
1260 /* iterative version */
1262 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1265 register double xmid
, ymid
;
1266 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1269 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1271 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1272 xmid
= (double)half(x2
, x3
);
1273 ymid
= (double)half(y2
, y3
);
1274 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1275 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1276 wx_spline_add_point( x1
, y1
);
1277 wx_spline_add_point( xmid
, ymid
);
1279 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1280 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1281 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1282 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1287 /* utilities used by spline drawing routines */
1289 typedef struct wx_spline_stack_struct
{
1290 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1293 #define SPLINE_STACK_DEPTH 20
1294 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1295 static Stack
*wx_stack_top
;
1296 static int wx_stack_count
;
1298 void wx_clear_stack()
1300 wx_stack_top
= wx_spline_stack
;
1304 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1306 wx_stack_top
->x1
= x1
;
1307 wx_stack_top
->y1
= y1
;
1308 wx_stack_top
->x2
= x2
;
1309 wx_stack_top
->y2
= y2
;
1310 wx_stack_top
->x3
= x3
;
1311 wx_stack_top
->y3
= y3
;
1312 wx_stack_top
->x4
= x4
;
1313 wx_stack_top
->y4
= y4
;
1318 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1319 double *x3
, double *y3
, double *x4
, double *y4
)
1321 if (wx_stack_count
== 0)
1325 *x1
= wx_stack_top
->x1
;
1326 *y1
= wx_stack_top
->y1
;
1327 *x2
= wx_stack_top
->x2
;
1328 *y2
= wx_stack_top
->y2
;
1329 *x3
= wx_stack_top
->x3
;
1330 *y3
= wx_stack_top
->y3
;
1331 *x4
= wx_stack_top
->x4
;
1332 *y4
= wx_stack_top
->y4
;
1336 static bool wx_spline_add_point(double x
, double y
)
1338 wxPoint
*point
= new wxPoint
;
1341 wx_spline_point_list
.Append((wxObject
*)point
);
1345 static void wx_spline_draw_point_array(wxDC
*dc
)
1347 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1348 wxNode
*node
= wx_spline_point_list
.First();
1351 wxPoint
*point
= (wxPoint
*)node
->Data();
1354 node
= wx_spline_point_list
.First();
1358 void wxWindowDC::DoDrawSpline( wxList
*points
)
1360 wxCHECK_RET( Ok(), _T("invalid window dc") );
1363 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1364 double x1
, y1
, x2
, y2
;
1366 wxNode
*node
= points
->First();
1367 p
= (wxPoint
*)node
->Data();
1372 node
= node
->Next();
1373 p
= (wxPoint
*)node
->Data();
1377 cx1
= (double)((x1
+ x2
) / 2);
1378 cy1
= (double)((y1
+ y2
) / 2);
1379 cx2
= (double)((cx1
+ x2
) / 2);
1380 cy2
= (double)((cy1
+ y2
) / 2);
1382 wx_spline_add_point(x1
, y1
);
1384 while ((node
= node
->Next()) != NULL
)
1386 p
= (wxPoint
*)node
->Data();
1391 cx4
= (double)(x1
+ x2
) / 2;
1392 cy4
= (double)(y1
+ y2
) / 2;
1393 cx3
= (double)(x1
+ cx4
) / 2;
1394 cy3
= (double)(y1
+ cy4
) / 2;
1396 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1400 cx2
= (double)(cx1
+ x2
) / 2;
1401 cy2
= (double)(cy1
+ y2
) / 2;
1404 wx_spline_add_point( cx1
, cy1
);
1405 wx_spline_add_point( x2
, y2
);
1407 wx_spline_draw_point_array( this );
1410 #endif // wxUSE_SPLINE
1412 //-----------------------------------------------------------------------------
1414 //-----------------------------------------------------------------------------
1416 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1418 wxPaintDC::wxPaintDC()
1423 wxPaintDC::wxPaintDC( wxWindow
*win
)
1428 //-----------------------------------------------------------------------------
1430 //-----------------------------------------------------------------------------
1432 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1434 wxClientDC::wxClientDC()
1439 wxClientDC::wxClientDC( wxWindow
*win
)