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
);
1175 tmp_brush
= m_backgroundBrush
;
1176 m_backgroundBrush
= wxNullBrush
;
1177 SetBackground( tmp_brush
);
1181 hatch_bitmap
= hatches
;
1182 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1183 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1184 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1185 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1186 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1187 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1191 void wxWindowDC::Destroy()
1193 if (m_penGC
) gdk_gc_unref( m_penGC
);
1194 m_penGC
= (GdkGC
*) NULL
;
1195 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1196 m_brushGC
= (GdkGC
*) NULL
;
1197 if (m_textGC
) gdk_gc_unref( m_textGC
);
1198 m_textGC
= (GdkGC
*) NULL
;
1199 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1200 m_bgGC
= (GdkGC
*) NULL
;
1203 void wxWindowDC::ComputeScaleAndOrigin()
1205 /* CMB: copy scale to see if it changes */
1206 double origScaleX
= m_scaleX
;
1207 double origScaleY
= m_scaleY
;
1209 wxDC::ComputeScaleAndOrigin();
1211 /* CMB: if scale has changed call SetPen to recalulate the line width */
1212 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1215 /* this is a bit artificial, but we need to force wxDC to think
1216 the pen has changed */
1223 // Resolution in pixels per logical inch
1224 wxSize
wxWindowDC::GetPPI() const
1226 return wxSize(100, 100);
1229 int wxWindowDC::GetDepth() const
1231 wxFAIL_MSG(_T("not implemented"));
1237 // ----------------------------------- spline code ----------------------------------------
1239 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1240 double a3
, double b3
, double a4
, double b4
);
1241 void wx_clear_stack();
1242 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1243 double *y3
, double *x4
, double *y4
);
1244 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1245 double x4
, double y4
);
1246 static bool wx_spline_add_point(double x
, double y
);
1247 static void wx_spline_draw_point_array(wxDC
*dc
);
1249 wxList wx_spline_point_list
;
1251 #define half(z1, z2) ((z1+z2)/2.0)
1254 /* iterative version */
1256 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1259 register double xmid
, ymid
;
1260 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1263 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1265 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1266 xmid
= (double)half(x2
, x3
);
1267 ymid
= (double)half(y2
, y3
);
1268 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1269 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1270 wx_spline_add_point( x1
, y1
);
1271 wx_spline_add_point( xmid
, ymid
);
1273 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1274 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1275 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1276 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1281 /* utilities used by spline drawing routines */
1283 typedef struct wx_spline_stack_struct
{
1284 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1287 #define SPLINE_STACK_DEPTH 20
1288 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1289 static Stack
*wx_stack_top
;
1290 static int wx_stack_count
;
1292 void wx_clear_stack()
1294 wx_stack_top
= wx_spline_stack
;
1298 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1300 wx_stack_top
->x1
= x1
;
1301 wx_stack_top
->y1
= y1
;
1302 wx_stack_top
->x2
= x2
;
1303 wx_stack_top
->y2
= y2
;
1304 wx_stack_top
->x3
= x3
;
1305 wx_stack_top
->y3
= y3
;
1306 wx_stack_top
->x4
= x4
;
1307 wx_stack_top
->y4
= y4
;
1312 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1313 double *x3
, double *y3
, double *x4
, double *y4
)
1315 if (wx_stack_count
== 0)
1319 *x1
= wx_stack_top
->x1
;
1320 *y1
= wx_stack_top
->y1
;
1321 *x2
= wx_stack_top
->x2
;
1322 *y2
= wx_stack_top
->y2
;
1323 *x3
= wx_stack_top
->x3
;
1324 *y3
= wx_stack_top
->y3
;
1325 *x4
= wx_stack_top
->x4
;
1326 *y4
= wx_stack_top
->y4
;
1330 static bool wx_spline_add_point(double x
, double y
)
1332 wxPoint
*point
= new wxPoint
;
1335 wx_spline_point_list
.Append((wxObject
*)point
);
1339 static void wx_spline_draw_point_array(wxDC
*dc
)
1341 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1342 wxNode
*node
= wx_spline_point_list
.First();
1345 wxPoint
*point
= (wxPoint
*)node
->Data();
1348 node
= wx_spline_point_list
.First();
1352 void wxWindowDC::DoDrawSpline( wxList
*points
)
1354 wxCHECK_RET( Ok(), _T("invalid window dc") );
1357 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1358 double x1
, y1
, x2
, y2
;
1360 wxNode
*node
= points
->First();
1361 p
= (wxPoint
*)node
->Data();
1366 node
= node
->Next();
1367 p
= (wxPoint
*)node
->Data();
1371 cx1
= (double)((x1
+ x2
) / 2);
1372 cy1
= (double)((y1
+ y2
) / 2);
1373 cx2
= (double)((cx1
+ x2
) / 2);
1374 cy2
= (double)((cy1
+ y2
) / 2);
1376 wx_spline_add_point(x1
, y1
);
1378 while ((node
= node
->Next()) != NULL
)
1380 p
= (wxPoint
*)node
->Data();
1385 cx4
= (double)(x1
+ x2
) / 2;
1386 cy4
= (double)(y1
+ y2
) / 2;
1387 cx3
= (double)(x1
+ cx4
) / 2;
1388 cy3
= (double)(y1
+ cy4
) / 2;
1390 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1394 cx2
= (double)(cx1
+ x2
) / 2;
1395 cy2
= (double)(cy1
+ y2
) / 2;
1398 wx_spline_add_point( cx1
, cy1
);
1399 wx_spline_add_point( x2
, y2
);
1401 wx_spline_draw_point_array( this );
1404 #endif // wxUSE_SPLINE
1406 //-----------------------------------------------------------------------------
1408 //-----------------------------------------------------------------------------
1410 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1412 wxPaintDC::wxPaintDC()
1417 wxPaintDC::wxPaintDC( wxWindow
*win
)
1422 //-----------------------------------------------------------------------------
1424 //-----------------------------------------------------------------------------
1426 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1428 wxClientDC::wxClientDC()
1433 wxClientDC::wxClientDC( wxWindow
*win
)