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
);
308 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
310 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
314 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
) )
316 wxCHECK_RET( Ok(), _T("invalid window dc") );
320 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
322 for (i
= 0 ; i
< n
; i
++)
324 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
325 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
327 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
330 if (m_brush
.GetStyle() != wxTRANSPARENT
)
331 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
335 if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
)
337 for (i
= 0 ; i
< n
; i
++)
339 gdk_draw_line( m_window
, m_penGC
,
342 gdkpoints
[(i
+1)%n
].x
,
343 gdkpoints
[(i
+1)%n
].y
);
350 void wxWindowDC::DoDrawRectangle( long x
, long y
, long width
, long height
)
352 wxCHECK_RET( Ok(), _T("invalid window dc") );
354 long xx
= XLOG2DEV(x
);
355 long yy
= YLOG2DEV(y
);
356 long ww
= m_signX
* XLOG2DEVREL(width
);
357 long hh
= m_signY
* YLOG2DEVREL(height
);
359 // CMB: draw nothing if transformed w or h is 0
360 if (ww
== 0 || hh
== 0) return;
362 // CMB: handle -ve width and/or height
363 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
364 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
368 if (m_brush
.GetStyle() != wxTRANSPARENT
)
369 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
371 if (m_pen
.GetStyle() != wxTRANSPARENT
)
372 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
375 CalcBoundingBox( x
, y
);
376 CalcBoundingBox( x
+ width
, y
+ height
);
379 void wxWindowDC::DoDrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
381 wxCHECK_RET( Ok(), _T("invalid window dc") );
383 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
385 long xx
= XLOG2DEV(x
);
386 long yy
= YLOG2DEV(y
);
387 long ww
= m_signX
* XLOG2DEVREL(width
);
388 long hh
= m_signY
* YLOG2DEVREL(height
);
389 long rr
= XLOG2DEVREL((long)radius
);
391 // CMB: handle -ve width and/or height
392 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
393 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
395 // CMB: if radius is zero use DrawRectangle() instead to avoid
396 // X drawing errors with small radii
399 DrawRectangle( x
, y
, width
, height
);
403 // CMB: draw nothing if transformed w or h is 0
404 if (ww
== 0 || hh
== 0) return;
406 // CMB: adjust size if outline is drawn otherwise the result is
407 // 1 pixel too wide and high
408 if (m_pen
.GetStyle() != wxTRANSPARENT
)
416 // CMB: ensure dd is not larger than rectangle otherwise we
417 // get an hour glass shape
419 if (dd
> ww
) dd
= ww
;
420 if (dd
> hh
) dd
= hh
;
423 if (m_brush
.GetStyle() != wxTRANSPARENT
)
425 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
426 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
427 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
428 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
429 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
430 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
433 if (m_pen
.GetStyle() != wxTRANSPARENT
)
435 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
436 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
437 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
438 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
439 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
440 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
441 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
442 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
446 // this ignores the radius
447 CalcBoundingBox( x
, y
);
448 CalcBoundingBox( x
+ width
, y
+ height
);
451 void wxWindowDC::DoDrawEllipse( long x
, long y
, long width
, long height
)
453 wxCHECK_RET( Ok(), _T("invalid window dc") );
455 long xx
= XLOG2DEV(x
);
456 long yy
= YLOG2DEV(y
);
457 long ww
= m_signX
* XLOG2DEVREL(width
);
458 long hh
= m_signY
* YLOG2DEVREL(height
);
460 // CMB: handle -ve width and/or height
461 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
462 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
466 if (m_brush
.GetStyle() != wxTRANSPARENT
)
467 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
469 if (m_pen
.GetStyle() != wxTRANSPARENT
)
470 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
473 CalcBoundingBox( x
- width
, y
- height
);
474 CalcBoundingBox( x
+ width
, y
+ height
);
477 void wxWindowDC::DoDrawIcon( const wxIcon
&icon
, long x
, long y
)
479 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
480 DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE
);
483 void wxWindowDC::DoDrawBitmap( const wxBitmap
&bitmap
,
487 wxCHECK_RET( Ok(), _T("invalid window dc") );
489 wxCHECK_RET( bitmap
.Ok(), _T("invalid bitmap") );
491 /* scale/translate size and position */
493 int xx
= XLOG2DEV(x
);
494 int yy
= YLOG2DEV(y
);
496 int w
= bitmap
.GetWidth();
497 int h
= bitmap
.GetHeight();
499 CalcBoundingBox( x
, y
);
500 CalcBoundingBox( x
+ w
, y
+ h
);
502 if (!m_window
) return;
504 int ww
= XLOG2DEVREL(w
);
505 int hh
= YLOG2DEVREL(h
);
507 /* scale bitmap if required */
511 if ((w
!= ww
) || (h
!= hh
))
513 wxImage
image( bitmap
);
514 image
= image
.Scale( ww
, hh
);
516 use_bitmap
= image
.ConvertToBitmap();
523 /* apply mask if any */
525 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
526 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
530 gdk_gc_set_clip_mask( m_penGC
, mask
);
531 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
534 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
536 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
539 gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 );
543 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
546 gdk_draw_bitmap( m_window
, m_penGC
, bm
, 0, 0, xx
, yy
, -1, -1 );
550 /* remove mask again if any */
554 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
555 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
559 bool wxWindowDC::DoBlit( long xdest
, long ydest
, long width
, long height
,
560 wxDC
*source
, long xsrc
, long ysrc
,
561 int logical_func
, bool useMask
)
563 /* this is the nth try to get this utterly useless function to
564 work. it now completely ignores the scaling or translation
565 of the source dc, but scales correctly on the target dc and
566 knows about possible mask information in a memory dc. */
568 wxCHECK_MSG( Ok(), FALSE
, _T("invalid window dc") );
570 wxCHECK_MSG( source
, FALSE
, _T("invalid source dc") );
572 if (!m_window
) return FALSE
;
574 wxClientDC
*srcDC
= (wxClientDC
*)source
;
575 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
577 bool use_bitmap_method
= FALSE
;
579 if (srcDC
->m_isMemDC
)
581 if (!memDC
->m_selected
.Ok()) return FALSE
;
583 /* we use the "XCopyArea" way to copy a memory dc into
584 y different window if the memory dc BOTH
585 a) doesn't have any mask or its mask isn't used
589 if (useMask
&& (memDC
->m_selected
.GetMask()))
591 /* we HAVE TO use the direct way for memory dcs
592 that have mask since the XCopyArea doesn't know
594 use_bitmap_method
= TRUE
;
596 else if (memDC
->m_selected
.GetDepth() == 1)
598 /* we HAVE TO use the direct way for memory dcs
599 that are bitmaps because XCopyArea doesn't cope
600 with different bit depths */
601 use_bitmap_method
= TRUE
;
603 else if ((xsrc
== 0) && (ysrc
== 0) &&
604 (width
== memDC
->m_selected
.GetWidth()) &&
605 (height
== memDC
->m_selected
.GetHeight()))
607 /* we SHOULD use the direct way if all of the bitmap
608 in the memory dc is copied in which case XCopyArea
609 wouldn't be able able to boost performace by reducing
610 the area to be scaled */
611 use_bitmap_method
= TRUE
;
615 use_bitmap_method
= FALSE
;
619 CalcBoundingBox( xdest
, ydest
);
620 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
622 int old_logical_func
= m_logicalFunction
;
623 SetLogicalFunction( logical_func
);
625 if (use_bitmap_method
)
627 /* scale/translate bitmap size */
629 long bm_width
= memDC
->m_selected
.GetWidth();
630 long bm_height
= memDC
->m_selected
.GetHeight();
632 long bm_ww
= XLOG2DEVREL( bm_width
);
633 long bm_hh
= YLOG2DEVREL( bm_height
);
635 /* scale bitmap if required */
639 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
641 wxImage
image( memDC
->m_selected
);
642 image
= image
.Scale( bm_ww
, bm_hh
);
644 use_bitmap
= image
.ConvertToBitmap();
648 use_bitmap
= memDC
->m_selected
;
651 /* scale/translate size and position */
653 long xx
= XLOG2DEV(xdest
);
654 long yy
= YLOG2DEV(ydest
);
656 long ww
= XLOG2DEVREL(width
);
657 long hh
= YLOG2DEVREL(height
);
659 /* apply mask if any */
661 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
662 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
666 gdk_gc_set_clip_mask( m_penGC
, mask
);
667 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
670 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
672 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
675 gdk_draw_pixmap( m_window
, m_penGC
, pm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
679 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
682 /* we use the textGC here because blitting a bitmap is done
683 using the current text colour */
684 gdk_draw_bitmap( m_window
, m_textGC
, bm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
688 /* remove mask again if any */
692 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
693 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
696 else /* use_bitmap_method */
698 /* scale/translate size and position */
700 long xx
= XLOG2DEV(xdest
);
701 long yy
= YLOG2DEV(ydest
);
703 long ww
= XLOG2DEVREL(width
);
704 long hh
= YLOG2DEVREL(height
);
706 if ((width
!= ww
) || (height
!= hh
))
708 /* draw source window into a bitmap as we cannot scale
709 a window in contrast to a bitmap. this would actually
710 work with memory dcs as well, but we'd lose the mask
711 information and waste one step in this process since
712 a memory already has a bitmap. all this is slightly
713 inefficient as we could take an XImage directly from
714 an X window, but we'd then also have to care that
715 the window is not outside the screen (in which case
716 we'd get a BadMatch or what not).
717 Is a double XGetImage and combined XGetPixel and
718 XPutPixel really faster? I'm not sure. look at wxXt
719 for a different implementation of the same problem. */
721 wxBitmap
bitmap( width
, height
);
722 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
724 xsrc
, ysrc
, width
, height
);
728 wxImage
image( bitmap
);
729 image
= image
.Scale( ww
, hh
);
731 /* convert to bitmap */
733 bitmap
= image
.ConvertToBitmap();
735 /* draw scaled bitmap */
737 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
742 /* no scaling and not a memory dc with a mask either */
744 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
746 xsrc
, ysrc
, width
, height
);
750 SetLogicalFunction( old_logical_func
);
754 void wxWindowDC::DoDrawText( const wxString
&text
, long x
, long y
)
756 wxCHECK_RET( Ok(), _T("invalid window dc") );
758 if (!m_window
) return;
760 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
765 /* CMB 21/5/98: draw text background if mode is wxSOLID */
766 if (m_backgroundMode
== wxSOLID
)
768 long width
= gdk_string_width( font
, text
.mbc_str() );
769 long height
= font
->ascent
+ font
->descent
;
770 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
771 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
772 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
774 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
776 /* CMB 17/7/98: simple underline: ignores scaling and underlying
777 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
778 properties (see wxXt implementation) */
779 if (m_font
.GetUnderlined())
781 long width
= gdk_string_width( font
, text
.mbc_str() );
782 long ul_y
= y
+ font
->ascent
;
783 if (font
->descent
> 0) ul_y
++;
784 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
788 GetTextExtent (text
, &w
, &h
);
789 CalcBoundingBox (x
+ w
, y
+ h
);
790 CalcBoundingBox (x
, y
);
793 void wxWindowDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
794 long *descent
, long *externalLeading
,
795 wxFont
*theFont
) const
797 wxFont fontToUse
= m_font
;
798 if (theFont
) fontToUse
= *theFont
;
800 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
801 if (width
) (*width
) = long(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
802 if (height
) (*height
) = long((font
->ascent
+ font
->descent
) / m_scaleY
);
803 if (descent
) (*descent
) = long(font
->descent
/ m_scaleY
);
804 if (externalLeading
) (*externalLeading
) = 0; // ??
807 long wxWindowDC::GetCharWidth() const
809 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
810 return long(gdk_string_width( font
, "H" ) / m_scaleX
);
813 long wxWindowDC::GetCharHeight() const
815 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
816 return long((font
->ascent
+ font
->descent
) / m_scaleY
);
819 void wxWindowDC::Clear()
821 wxCHECK_RET( Ok(), _T("invalid window dc") );
823 if (!m_window
) return;
825 /* - we either are a memory dc or have a window as the
826 owner. anything else shouldn't happen.
827 - we don't use gdk_window_clear() as we don't set
828 the window's background colour anymore. it is too
829 much pain to keep the DC's and the window's back-
830 ground colour in synch. */
835 m_owner
->GetSize( &width
, &height
);
836 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
843 GetSize( &width
, &height
);
844 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
849 void wxWindowDC::SetFont( const wxFont
&font
)
854 void wxWindowDC::SetPen( const wxPen
&pen
)
856 wxCHECK_RET( Ok(), _T("invalid window dc") );
858 if (m_pen
== pen
) return;
862 if (!m_pen
.Ok()) return;
864 if (!m_window
) return;
866 gint width
= m_pen
.GetWidth();
867 // CMB: if width is non-zero scale it with the dc
874 // X doesn't allow different width in x and y and so we take
876 double w
= 0.5 + (abs(XLOG2DEVREL(width
)) + abs(YLOG2DEVREL(width
))) / 2.0;
880 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
881 switch (m_pen
.GetStyle())
883 case wxSOLID
: { lineStyle
= GDK_LINE_SOLID
; break; }
884 case wxDOT
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
885 case wxLONG_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
886 case wxSHORT_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
887 case wxDOT_DASH
: { lineStyle
= GDK_LINE_DOUBLE_DASH
; break; }
890 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
891 switch (m_pen
.GetCap())
893 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
894 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
895 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
898 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
899 switch (m_pen
.GetJoin())
901 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
902 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
903 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
906 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
908 m_pen
.GetColour().CalcPixel( m_cmap
);
909 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
912 void wxWindowDC::SetBrush( const wxBrush
&brush
)
914 wxCHECK_RET( Ok(), _T("invalid window dc") );
916 if (m_brush
== brush
) return;
920 if (!m_brush
.Ok()) return;
922 if (!m_window
) return;
924 m_brush
.GetColour().CalcPixel( m_cmap
);
925 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
927 GdkFill fillStyle
= GDK_SOLID
;
928 switch (m_brush
.GetStyle())
934 fillStyle
= GDK_STIPPLED
;
937 gdk_gc_set_fill( m_brushGC
, fillStyle
);
939 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
941 if (m_brush
.GetStipple()->GetPixmap())
942 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
944 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
947 if (IS_HATCH(m_brush
.GetStyle()))
949 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
950 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
954 void wxWindowDC::SetBackground( const wxBrush
&brush
)
956 /* CMB 21/7/98: Added SetBackground. Sets background brush
957 * for Clear() and bg colour for shapes filled with cross-hatch brush */
959 wxCHECK_RET( Ok(), _T("invalid window dc") );
961 if (m_backgroundBrush
== brush
) return;
963 m_backgroundBrush
= brush
;
965 if (!m_backgroundBrush
.Ok()) return;
967 if (!m_window
) return;
969 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
970 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
971 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
972 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
973 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
975 GdkFill fillStyle
= GDK_SOLID
;
976 switch (m_backgroundBrush
.GetStyle())
982 fillStyle
= GDK_STIPPLED
;
985 gdk_gc_set_fill( m_bgGC
, fillStyle
);
987 if (m_backgroundBrush
.GetStyle() == wxSTIPPLE
)
989 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
992 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
994 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
995 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
999 void wxWindowDC::SetLogicalFunction( int function
)
1001 wxCHECK_RET( Ok(), _T("invalid window dc") );
1003 if (m_logicalFunction
== function
) return;
1005 GdkFunction mode
= GDK_COPY
;
1008 case wxXOR
: mode
= GDK_XOR
; break;
1009 case wxINVERT
: mode
= GDK_INVERT
; break;
1010 #if (GTK_MINOR_VERSION > 0)
1011 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1012 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1013 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1014 case wxSET
: mode
= GDK_SET
; break;
1015 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1017 case wxAND
: mode
= GDK_AND
; break;
1019 case wxOR
: mode
= GDK_OR
; break;
1020 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1021 case wxNAND
: mode
= GDK_NAND
; break;
1022 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1023 case wxCOPY
: mode
= GDK_COPY
; break;
1024 case wxNO_OP
: mode
= GDK_NOOP
; break;
1025 case wxSRC_INVERT
: mode
= GDK_COPY_INVERT
; break;
1029 wxFAIL_MSG( _T("unsupported logical function") );
1034 m_logicalFunction
= function
;
1036 if (!m_window
) return;
1038 gdk_gc_set_function( m_penGC
, mode
);
1039 gdk_gc_set_function( m_brushGC
, mode
);
1040 gdk_gc_set_function( m_textGC
, mode
);
1043 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1045 wxCHECK_RET( Ok(), _T("invalid window dc") );
1047 if (m_textForegroundColour
== col
) return;
1049 m_textForegroundColour
= col
;
1050 if (!m_textForegroundColour
.Ok()) return;
1052 if (!m_window
) return;
1054 m_textForegroundColour
.CalcPixel( m_cmap
);
1055 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1058 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1060 wxCHECK_RET( Ok(), _T("invalid window dc") );
1062 if (m_textBackgroundColour
== col
) return;
1064 m_textBackgroundColour
= col
;
1065 if (!m_textBackgroundColour
.Ok()) return;
1067 if (!m_window
) return;
1069 m_textBackgroundColour
.CalcPixel( m_cmap
);
1070 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1073 void wxWindowDC::SetBackgroundMode( int mode
)
1075 wxCHECK_RET( Ok(), _T("invalid window dc") );
1077 m_backgroundMode
= mode
;
1079 if (!m_window
) return;
1081 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1082 // transparent/solid background mode
1084 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1086 gdk_gc_set_fill( m_brushGC
,
1087 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1091 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1093 wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") );
1096 void wxWindowDC::DoSetClippingRegion( long x
, long y
, long width
, long height
)
1098 wxCHECK_RET( Ok(), _T("invalid window dc") );
1100 wxDC::DoSetClippingRegion( x
, y
, width
, height
);
1102 if (!m_window
) return;
1105 rect
.x
= XLOG2DEV(x
);
1106 rect
.y
= YLOG2DEV(y
);
1107 rect
.width
= XLOG2DEVREL(width
);
1108 rect
.height
= YLOG2DEVREL(height
);
1109 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1110 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1111 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1112 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1115 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion
®ion
)
1117 wxCHECK_RET( Ok(), _T("invalid window dc") );
1121 DestroyClippingRegion();
1125 if (!m_window
) return;
1127 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1128 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1129 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1130 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1133 void wxWindowDC::DestroyClippingRegion()
1135 wxCHECK_RET( Ok(), _T("invalid window dc") );
1137 wxDC::DestroyClippingRegion();
1139 if (!m_window
) return;
1141 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1142 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1143 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1144 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1147 void wxWindowDC::SetUpDC()
1151 m_logicalFunction
= wxCOPY
;
1152 m_penGC
= gdk_gc_new( m_window
);
1153 m_brushGC
= gdk_gc_new( m_window
);
1154 m_textGC
= gdk_gc_new( m_window
);
1155 m_bgGC
= gdk_gc_new( m_window
);
1157 wxColour
tmp_col( m_textForegroundColour
);
1158 m_textForegroundColour
= wxNullColour
;
1159 SetTextForeground( tmp_col
);
1160 tmp_col
= m_textBackgroundColour
;
1161 m_textBackgroundColour
= wxNullColour
;
1162 SetTextBackground( tmp_col
);
1164 wxPen
tmp_pen( m_pen
);
1168 wxFont
tmp_font( m_font
);
1169 m_font
= wxNullFont
;
1170 SetFont( tmp_font
);
1172 wxBrush
tmp_brush( m_brush
);
1173 m_brush
= wxNullBrush
;
1174 SetBrush( tmp_brush
);
1177 tmp_brush = m_backgroundBrush;
1178 m_backgroundBrush = wxNullBrush;
1179 SetBackground( tmp_brush );
1181 tmp_brush
= m_backgroundBrush
;
1182 m_backgroundBrush
= wxNullBrush
;
1183 SetBackground( *wxWHITE_BRUSH
);
1184 m_backgroundBrush
= tmp_brush
;
1188 hatch_bitmap
= hatches
;
1189 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1190 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1191 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1192 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1193 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1194 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1198 void wxWindowDC::Destroy()
1200 if (m_penGC
) gdk_gc_unref( m_penGC
);
1201 m_penGC
= (GdkGC
*) NULL
;
1202 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1203 m_brushGC
= (GdkGC
*) NULL
;
1204 if (m_textGC
) gdk_gc_unref( m_textGC
);
1205 m_textGC
= (GdkGC
*) NULL
;
1206 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1207 m_bgGC
= (GdkGC
*) NULL
;
1210 void wxWindowDC::ComputeScaleAndOrigin()
1212 /* CMB: copy scale to see if it changes */
1213 double origScaleX
= m_scaleX
;
1214 double origScaleY
= m_scaleY
;
1216 wxDC::ComputeScaleAndOrigin();
1218 /* CMB: if scale has changed call SetPen to recalulate the line width */
1219 if ((m_scaleX
!= origScaleX
|| m_scaleY
!= origScaleY
) &&
1222 /* this is a bit artificial, but we need to force wxDC to think
1223 the pen has changed */
1230 // Resolution in pixels per logical inch
1231 wxSize
wxWindowDC::GetPPI() const
1233 return wxSize(100, 100);
1236 int wxWindowDC::GetDepth() const
1238 wxFAIL_MSG(_T("not implemented"));
1244 // ----------------------------------- spline code ----------------------------------------
1246 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1247 double a3
, double b3
, double a4
, double b4
);
1248 void wx_clear_stack();
1249 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1250 double *y3
, double *x4
, double *y4
);
1251 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1252 double x4
, double y4
);
1253 static bool wx_spline_add_point(double x
, double y
);
1254 static void wx_spline_draw_point_array(wxDC
*dc
);
1256 wxList wx_spline_point_list
;
1258 #define half(z1, z2) ((z1+z2)/2.0)
1261 /* iterative version */
1263 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1266 register double xmid
, ymid
;
1267 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1270 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1272 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1273 xmid
= (double)half(x2
, x3
);
1274 ymid
= (double)half(y2
, y3
);
1275 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1276 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1277 wx_spline_add_point( x1
, y1
);
1278 wx_spline_add_point( xmid
, ymid
);
1280 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1281 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1282 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1283 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1288 /* utilities used by spline drawing routines */
1290 typedef struct wx_spline_stack_struct
{
1291 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1294 #define SPLINE_STACK_DEPTH 20
1295 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1296 static Stack
*wx_stack_top
;
1297 static int wx_stack_count
;
1299 void wx_clear_stack()
1301 wx_stack_top
= wx_spline_stack
;
1305 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1307 wx_stack_top
->x1
= x1
;
1308 wx_stack_top
->y1
= y1
;
1309 wx_stack_top
->x2
= x2
;
1310 wx_stack_top
->y2
= y2
;
1311 wx_stack_top
->x3
= x3
;
1312 wx_stack_top
->y3
= y3
;
1313 wx_stack_top
->x4
= x4
;
1314 wx_stack_top
->y4
= y4
;
1319 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1320 double *x3
, double *y3
, double *x4
, double *y4
)
1322 if (wx_stack_count
== 0)
1326 *x1
= wx_stack_top
->x1
;
1327 *y1
= wx_stack_top
->y1
;
1328 *x2
= wx_stack_top
->x2
;
1329 *y2
= wx_stack_top
->y2
;
1330 *x3
= wx_stack_top
->x3
;
1331 *y3
= wx_stack_top
->y3
;
1332 *x4
= wx_stack_top
->x4
;
1333 *y4
= wx_stack_top
->y4
;
1337 static bool wx_spline_add_point(double x
, double y
)
1339 wxPoint
*point
= new wxPoint
;
1342 wx_spline_point_list
.Append((wxObject
*)point
);
1346 static void wx_spline_draw_point_array(wxDC
*dc
)
1348 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1349 wxNode
*node
= wx_spline_point_list
.First();
1352 wxPoint
*point
= (wxPoint
*)node
->Data();
1355 node
= wx_spline_point_list
.First();
1359 void wxWindowDC::DoDrawSpline( wxList
*points
)
1361 wxCHECK_RET( Ok(), _T("invalid window dc") );
1364 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1365 double x1
, y1
, x2
, y2
;
1367 wxNode
*node
= points
->First();
1368 p
= (wxPoint
*)node
->Data();
1373 node
= node
->Next();
1374 p
= (wxPoint
*)node
->Data();
1378 cx1
= (double)((x1
+ x2
) / 2);
1379 cy1
= (double)((y1
+ y2
) / 2);
1380 cx2
= (double)((cx1
+ x2
) / 2);
1381 cy2
= (double)((cy1
+ y2
) / 2);
1383 wx_spline_add_point(x1
, y1
);
1385 while ((node
= node
->Next()) != NULL
)
1387 p
= (wxPoint
*)node
->Data();
1392 cx4
= (double)(x1
+ x2
) / 2;
1393 cy4
= (double)(y1
+ y2
) / 2;
1394 cx3
= (double)(x1
+ cx4
) / 2;
1395 cy3
= (double)(y1
+ cy4
) / 2;
1397 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1401 cx2
= (double)(cx1
+ x2
) / 2;
1402 cy2
= (double)(cy1
+ y2
) / 2;
1405 wx_spline_add_point( cx1
, cy1
);
1406 wx_spline_add_point( x2
, y2
);
1408 wx_spline_draw_point_array( this );
1411 #endif // wxUSE_SPLINE
1413 //-----------------------------------------------------------------------------
1415 //-----------------------------------------------------------------------------
1417 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1419 wxPaintDC::wxPaintDC()
1424 wxPaintDC::wxPaintDC( wxWindow
*win
)
1429 //-----------------------------------------------------------------------------
1431 //-----------------------------------------------------------------------------
1433 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1435 wxClientDC::wxClientDC()
1440 wxClientDC::wxClientDC( wxWindow
*win
)