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 //-----------------------------------------------------------------------------
46 #include "gdk/gdkprivate.h"
47 void gdk_draw_bitmap (GdkDrawable
*drawable
,
57 GdkWindowPrivate
*drawable_private
;
58 GdkWindowPrivate
*src_private
;
59 GdkGCPrivate
*gc_private
;
61 g_return_if_fail (drawable
!= NULL
);
62 g_return_if_fail (src
!= NULL
);
63 g_return_if_fail (gc
!= NULL
);
65 drawable_private
= (GdkWindowPrivate
*) drawable
;
66 src_private
= (GdkWindowPrivate
*) src
;
67 if (drawable_private
->destroyed
|| src_private
->destroyed
)
70 gc_private
= (GdkGCPrivate
*) gc
;
72 if (width
== -1) width
= src_private
->width
;
73 if (height
== -1) height
= src_private
->height
;
75 XCopyPlane( drawable_private
->xdisplay
,
77 drawable_private
->xwindow
,
85 //-----------------------------------------------------------------------------
87 //-----------------------------------------------------------------------------
89 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
,wxDC
)
91 wxWindowDC::wxWindowDC()
93 m_penGC
= (GdkGC
*) NULL
;
94 m_brushGC
= (GdkGC
*) NULL
;
95 m_textGC
= (GdkGC
*) NULL
;
96 m_bgGC
= (GdkGC
*) NULL
;
97 m_cmap
= (GdkColormap
*) NULL
;
99 m_owner
= (wxWindow
*)NULL
;
102 wxWindowDC::wxWindowDC( wxWindow
*window
)
104 m_penGC
= (GdkGC
*) NULL
;
105 m_brushGC
= (GdkGC
*) NULL
;
106 m_textGC
= (GdkGC
*) NULL
;
107 m_bgGC
= (GdkGC
*) NULL
;
108 m_cmap
= (GdkColormap
*) NULL
;
109 m_owner
= (wxWindow
*)NULL
;
113 GtkWidget
*widget
= window
->m_wxwindow
;
117 m_window
= widget
->window
;
122 /* force realization */
123 gtk_widget_realize( widget
);
124 m_window
= widget
->window
;
127 /* still not realized ? */
128 if (!m_window
) return;
130 if (window
->m_wxwindow
)
131 m_cmap
= gtk_widget_get_colormap( window
->m_wxwindow
);
133 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::FloodFill( long WXUNUSED(x
), long WXUNUSED(y
),
155 const wxColour
&WXUNUSED(col
), int WXUNUSED(style
) )
157 wxFAIL_MSG( _T("wxWindowDC::FloodFill not implemented") );
160 bool wxWindowDC::GetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour
*WXUNUSED(col
) ) const
162 wxFAIL_MSG( _T("wxWindowDC::GetPixel not implemented") );
166 void wxWindowDC::DrawLine( long x1
, long y1
, long x2
, long y2
)
168 wxCHECK_RET( Ok(), _T("invalid window dc") );
170 if (m_pen
.GetStyle() != wxTRANSPARENT
)
172 gdk_draw_line( m_window
, m_penGC
,
173 XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) );
175 CalcBoundingBox(x1
, y1
);
176 CalcBoundingBox(x2
, y2
);
180 void wxWindowDC::CrossHair( 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
);
191 gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy
);
192 gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) );
196 void wxWindowDC::DrawArc( long x1
, long y1
, long x2
, long y2
, double xc
, double yc
)
198 wxCHECK_RET( Ok(), _T("invalid window dc") );
200 long xx1
= XLOG2DEV(x1
);
201 long yy1
= YLOG2DEV(y1
);
202 long xx2
= XLOG2DEV(x2
);
203 long yy2
= YLOG2DEV(y2
);
204 long xxc
= XLOG2DEV((long)xc
);
205 long yyc
= YLOG2DEV((long)yc
);
206 double dx
= xx1
- xxc
;
207 double dy
= yy1
- yyc
;
208 double radius
= sqrt(dx
*dx
+dy
*dy
);
209 long r
= (long)radius
;
210 double radius1
, radius2
;
212 if (xx1
== xx2
&& yy1
== yy2
)
220 radius1
= radius2
= 0.0;
224 radius1
= (xx1
- xxc
== 0) ?
225 (yy1
- yyc
< 0) ? 90.0 : -90.0 :
226 -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
;
227 radius2
= (xx2
- xxc
== 0) ?
228 (yy2
- yyc
< 0) ? 90.0 : -90.0 :
229 -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
;
231 long alpha1
= long(radius1
* 64.0);
232 long alpha2
= long((radius2
- radius1
) * 64.0);
233 while (alpha2
<= 0) alpha2
+= 360*64;
234 while (alpha1
> 360*64) alpha1
-= 360*64;
236 if (m_brush
.GetStyle() != wxTRANSPARENT
)
237 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
239 if (m_pen
.GetStyle() != wxTRANSPARENT
)
240 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2
);
242 CalcBoundingBox (x1
, y1
);
243 CalcBoundingBox (x2
, y2
);
246 void wxWindowDC::DrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea
)
248 wxCHECK_RET( Ok(), _T("invalid window dc") );
250 long xx
= XLOG2DEV(x
);
251 long yy
= YLOG2DEV(y
);
252 long ww
= m_signX
* XLOG2DEVREL(width
);
253 long hh
= m_signY
* YLOG2DEVREL(height
);
255 // CMB: handle -ve width and/or height
256 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
257 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
259 long start
= long(sa
* 64.0);
260 long end
= long(ea
* 64.0);
261 if (m_brush
.GetStyle() != wxTRANSPARENT
)
262 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end
);
264 if (m_pen
.GetStyle() != wxTRANSPARENT
)
265 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end
);
267 CalcBoundingBox (x
, y
);
268 CalcBoundingBox (x
+ width
, y
+ height
);
271 void wxWindowDC::DrawPoint( long x
, long y
)
273 wxCHECK_RET( Ok(), _T("invalid window dc") );
275 if (m_pen
.GetStyle() != wxTRANSPARENT
)
276 gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) );
278 CalcBoundingBox (x
, y
);
281 void wxWindowDC::DrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset
)
283 wxCHECK_RET( Ok(), _T("invalid window dc") );
285 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
288 CalcBoundingBox( points
[0].x
+ xoffset
, points
[0].y
+ yoffset
);
290 for (int i
= 0; i
< n
-1; i
++)
292 long x1
= XLOG2DEV(points
[i
].x
+ xoffset
);
293 long x2
= XLOG2DEV(points
[i
+1].x
+ xoffset
);
294 long y1
= YLOG2DEV(points
[i
].y
+ yoffset
); // oh, what a waste
295 long y2
= YLOG2DEV(points
[i
+1].y
+ yoffset
);
296 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
298 CalcBoundingBox( points
[i
+1].x
+ xoffset
, points
[i
+1].y
+ yoffset
);
302 void wxWindowDC::DrawLines( wxList
*points
, long xoffset
, long yoffset
)
304 wxCHECK_RET( Ok(), _T("invalid window dc") );
306 if (m_pen
.GetStyle() == wxTRANSPARENT
) return;
308 wxNode
*node
= points
->First();
311 wxPoint
*pt
= (wxPoint
*)node
->Data();
312 CalcBoundingBox( pt
->x
+ xoffset
, pt
->y
+ yoffset
);
316 wxPoint
*point
= (wxPoint
*)node
->Data();
317 wxPoint
*npoint
= (wxPoint
*)node
->Next()->Data();
318 long x1
= XLOG2DEV(point
->x
+ xoffset
);
319 long x2
= XLOG2DEV(npoint
->x
+ xoffset
);
320 long y1
= YLOG2DEV(point
->y
+ yoffset
); // and a waste again...
321 long y2
= YLOG2DEV(npoint
->y
+ yoffset
);
322 gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2
);
325 CalcBoundingBox( npoint
->x
+ xoffset
, npoint
->y
+ yoffset
);
329 void wxWindowDC::DrawPolygon( int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
) )
331 wxCHECK_RET( Ok(), _T("invalid window dc") );
335 GdkPoint
*gdkpoints
= new GdkPoint
[n
+1];
337 for (i
= 0 ; i
< n
; i
++)
339 gdkpoints
[i
].x
= XLOG2DEV(points
[i
].x
+ xoffset
);
340 gdkpoints
[i
].y
= YLOG2DEV(points
[i
].y
+ yoffset
);
342 CalcBoundingBox( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
);
345 if (m_brush
.GetStyle() != wxTRANSPARENT
)
346 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
350 if (m_pen
.GetStyle() != wxTRANSPARENT
)
351 for (i
= 0 ; i
< n
; i
++)
353 gdk_draw_line( m_window
, m_penGC
,
356 gdkpoints
[(i
+1)%n
].x
,
357 gdkpoints
[(i
+1)%n
].y
);
363 void wxWindowDC::DrawPolygon( wxList
*lines
, long xoffset
, long yoffset
, int WXUNUSED(fillStyle
))
365 wxCHECK_RET( Ok(), _T("invalid window dc") );
367 int n
= lines
->Number();
370 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
371 wxNode
*node
= lines
->First();
375 wxPoint
*p
= (wxPoint
*) node
->Data();
376 gdkpoints
[cnt
].x
= XLOG2DEV(p
->x
+ xoffset
);
377 gdkpoints
[cnt
].y
= YLOG2DEV(p
->y
+ yoffset
);
381 CalcBoundingBox( p
->x
+ xoffset
, p
->y
+ yoffset
);
384 if (m_brush
.GetStyle() != wxTRANSPARENT
)
385 gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
);
389 if (m_pen
.GetStyle() != wxTRANSPARENT
)
392 for (i
= 0 ; i
< n
; i
++)
394 gdk_draw_line( m_window
, m_penGC
,
397 gdkpoints
[(i
+1)%n
].x
,
398 gdkpoints
[(i
+1)%n
].y
);
404 void wxWindowDC::DrawRectangle( long x
, long y
, long width
, long height
)
406 wxCHECK_RET( Ok(), _T("invalid window dc") );
408 long xx
= XLOG2DEV(x
);
409 long yy
= YLOG2DEV(y
);
410 long ww
= m_signX
* XLOG2DEVREL(width
);
411 long hh
= m_signY
* YLOG2DEVREL(height
);
413 // CMB: draw nothing if transformed w or h is 0
414 if (ww
== 0 || hh
== 0) return;
416 // CMB: handle -ve width and/or height
417 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
418 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
420 if (m_brush
.GetStyle() != wxTRANSPARENT
)
421 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
);
423 if (m_pen
.GetStyle() != wxTRANSPARENT
)
424 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 );
426 CalcBoundingBox( x
, y
);
427 CalcBoundingBox( x
+ width
, y
+ height
);
430 void wxWindowDC::DrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius
)
432 wxCHECK_RET( Ok(), _T("invalid window dc") );
434 if (radius
< 0.0) radius
= - radius
* ((width
< height
) ? width
: height
);
436 long xx
= XLOG2DEV(x
);
437 long yy
= YLOG2DEV(y
);
438 long ww
= m_signX
* XLOG2DEVREL(width
);
439 long hh
= m_signY
* YLOG2DEVREL(height
);
440 long rr
= XLOG2DEVREL((long)radius
);
442 // CMB: handle -ve width and/or height
443 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
444 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
446 // CMB: if radius is zero use DrawRectangle() instead to avoid
447 // X drawing errors with small radii
450 DrawRectangle( x
, y
, width
, height
);
454 // CMB: draw nothing if transformed w or h is 0
455 if (ww
== 0 || hh
== 0) return;
457 // CMB: adjust size if outline is drawn otherwise the result is
458 // 1 pixel too wide and high
459 if (m_pen
.GetStyle() != wxTRANSPARENT
)
465 // CMB: ensure dd is not larger than rectangle otherwise we
466 // get an hour glass shape
468 if (dd
> ww
) dd
= ww
;
469 if (dd
> hh
) dd
= hh
;
472 if (m_brush
.GetStyle() != wxTRANSPARENT
)
474 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh
);
475 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 );
476 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
477 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
478 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
479 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
482 if (m_pen
.GetStyle() != wxTRANSPARENT
)
484 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy
);
485 gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh
);
486 gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr
);
487 gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr
);
488 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 );
489 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 );
490 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 );
491 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 );
494 // this ignores the radius
495 CalcBoundingBox( x
, y
);
496 CalcBoundingBox( x
+ width
, y
+ height
);
499 void wxWindowDC::DrawEllipse( long x
, long y
, long width
, long height
)
501 wxCHECK_RET( Ok(), _T("invalid window dc") );
503 long xx
= XLOG2DEV(x
);
504 long yy
= YLOG2DEV(y
);
505 long ww
= m_signX
* XLOG2DEVREL(width
);
506 long hh
= m_signY
* YLOG2DEVREL(height
);
508 // CMB: handle -ve width and/or height
509 if (ww
< 0) { ww
= -ww
; xx
= xx
- ww
; }
510 if (hh
< 0) { hh
= -hh
; yy
= yy
- hh
; }
512 if (m_brush
.GetStyle() != wxTRANSPARENT
)
513 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 );
515 if (m_pen
.GetStyle() != wxTRANSPARENT
)
516 gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 );
518 CalcBoundingBox( x
- width
, y
- height
);
519 CalcBoundingBox( x
+ width
, y
+ height
);
522 bool wxWindowDC::CanDrawBitmap() const
527 void wxWindowDC::DrawIcon( const wxIcon
&icon
, long x
, long y
)
529 DrawBitmap( icon
, x
, y
, TRUE
);
532 void wxWindowDC::DrawBitmap( const wxBitmap
&bitmap
, long x
, long y
, bool useMask
)
534 wxCHECK_RET( Ok(), _T("invalid window dc") );
536 if (!bitmap
.Ok()) return;
538 /* scale/translate size and position */
540 int xx
= XLOG2DEV(x
);
541 int yy
= YLOG2DEV(y
);
543 int w
= bitmap
.GetWidth();
544 int h
= bitmap
.GetHeight();
546 int ww
= XLOG2DEVREL(w
);
547 int hh
= YLOG2DEVREL(h
);
549 /* scale bitmap if required */
553 if ((w
!= ww
) || (h
!= hh
))
555 wxImage
image( bitmap
);
556 image
= image
.Scale( ww
, hh
);
558 use_bitmap
= image
.ConvertToBitmap();
565 /* apply mask if any */
567 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
568 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
572 gdk_gc_set_clip_mask( m_penGC
, mask
);
573 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
576 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
578 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
581 gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 );
585 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
588 gdk_draw_bitmap( m_window
, m_penGC
, bm
, 0, 0, xx
, yy
, -1, -1 );
592 /* remove mask again if any */
596 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
597 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
600 CalcBoundingBox( x
, y
);
601 CalcBoundingBox( x
+ w
, y
+ h
);
604 bool wxWindowDC::Blit( long xdest
, long ydest
, long width
, long height
,
605 wxDC
*source
, long xsrc
, long ysrc
, int logical_func
, bool useMask
)
607 /* this is the nth try to get this utterly useless function to
608 work. it now completely ignores the scaling or translation
609 of the source dc, but scales correctly on the target dc and
610 knows about possible mask information in a memory dc. */
612 wxCHECK_MSG( Ok(), FALSE
, _T("invalid window dc") );
614 wxCHECK_MSG( source
, FALSE
, _T("invalid source dc") );
616 wxClientDC
*srcDC
= (wxClientDC
*)source
;
617 wxMemoryDC
*memDC
= (wxMemoryDC
*)source
;
619 bool use_bitmap_method
= FALSE
;
621 if (srcDC
->m_isMemDC
)
623 if (!memDC
->m_selected
.Ok()) return FALSE
;
625 /* we use the "XCopyArea" way to copy a memory dc into
626 y different window if the memory dc BOTH
627 a) doesn't have any mask or its mask isn't used
631 if (useMask
&& (memDC
->m_selected
.GetMask()))
633 /* we HAVE TO use the direct way for memory dcs
634 that have mask since the XCopyArea doesn't know
636 use_bitmap_method
= TRUE
;
638 else if (memDC
->m_selected
.GetDepth() == 1)
640 /* we HAVE TO use the direct way for memory dcs
641 that are bitmaps because XCopyArea doesn't cope
642 with different bit depths */
643 use_bitmap_method
= TRUE
;
645 else if ((xsrc
== 0) && (ysrc
== 0) &&
646 (width
== memDC
->m_selected
.GetWidth()) &&
647 (height
== memDC
->m_selected
.GetHeight()))
649 /* we SHOULD use the direct way if all of the bitmap
650 in the memory dc is copied in which case XCopyArea
651 wouldn't be able able to boost performace by reducing
652 the area to be scaled */
653 use_bitmap_method
= TRUE
;
657 use_bitmap_method
= FALSE
;
661 CalcBoundingBox( xdest
, ydest
);
662 CalcBoundingBox( xdest
+ width
, ydest
+ height
);
664 int old_logical_func
= m_logicalFunction
;
665 SetLogicalFunction( logical_func
);
667 if (use_bitmap_method
)
669 /* scale/translate bitmap size */
671 long bm_width
= memDC
->m_selected
.GetWidth();
672 long bm_height
= memDC
->m_selected
.GetHeight();
674 long bm_ww
= XLOG2DEVREL( bm_width
);
675 long bm_hh
= YLOG2DEVREL( bm_height
);
677 /* scale bitmap if required */
681 if ((bm_width
!= bm_ww
) || (bm_height
!= bm_hh
))
683 wxImage
image( memDC
->m_selected
);
684 image
= image
.Scale( bm_ww
, bm_hh
);
686 use_bitmap
= image
.ConvertToBitmap();
690 use_bitmap
= memDC
->m_selected
;
693 /* scale/translate size and position */
695 long xx
= XLOG2DEV(xdest
);
696 long yy
= YLOG2DEV(ydest
);
698 long ww
= XLOG2DEVREL(width
);
699 long hh
= YLOG2DEVREL(height
);
701 /* apply mask if any */
703 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
704 if (use_bitmap
.GetMask()) mask
= use_bitmap
.GetMask()->GetBitmap();
708 gdk_gc_set_clip_mask( m_penGC
, mask
);
709 gdk_gc_set_clip_origin( m_penGC
, xx
, yy
);
712 /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
714 GdkPixmap
*pm
= use_bitmap
.GetPixmap();
717 gdk_draw_pixmap( m_window
, m_penGC
, pm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
721 GdkBitmap
*bm
= use_bitmap
.GetBitmap();
724 /* we use the textGC here because blitting a bitmap is done
725 using the current text colour */
726 gdk_draw_bitmap( m_window
, m_textGC
, bm
, xsrc
, ysrc
, xx
, yy
, ww
, hh
);
730 /* remove mask again if any */
734 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap
*) NULL
);
735 gdk_gc_set_clip_origin( m_penGC
, 0, 0 );
738 else /* use_bitmap_method */
740 /* scale/translate size and position */
742 long xx
= XLOG2DEV(xdest
);
743 long yy
= YLOG2DEV(ydest
);
745 long ww
= XLOG2DEVREL(width
);
746 long hh
= YLOG2DEVREL(height
);
748 if ((width
!= ww
) || (height
!= hh
))
750 /* draw source window into a bitmap as we cannot scale
751 a window in contrast to a bitmap. this would actually
752 work with memory dcs as well, but we'd lose the mask
753 information and waste one step in this process since
754 a memory already has a bitmap. all this is slightly
755 inefficient as we could take an XImage directly from
756 an X window, but we'd then also have to care that
757 the window is not outside the screen (in which case
758 we'd get a BadMatch or what not).
759 Is a double XGetImage and combined XGetPixel and
760 XPutPixel really faster? I'm not sure. look at wxXt
761 for a different implementation of the same problem. */
763 wxBitmap
bitmap( width
, height
);
764 gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,
766 xsrc
, ysrc
, width
, height
);
770 wxImage
image( bitmap
);
771 image
= image
.Scale( ww
, hh
);
773 /* convert to bitmap */
775 bitmap
= image
.ConvertToBitmap();
777 /* draw scaled bitmap */
779 gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 );
784 /* no scaling and not a memory dc with a mask either */
786 gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
,
788 xsrc
, ysrc
, width
, height
);
792 SetLogicalFunction( old_logical_func
);
796 void wxWindowDC::DrawText( const wxString
&text
, long x
, long y
, bool WXUNUSED(use16
) )
798 wxCHECK_RET( Ok(), _T("invalid window dc") );
800 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
805 /* CMB 21/5/98: draw text background if mode is wxSOLID */
806 if (m_backgroundMode
== wxSOLID
)
808 long width
= gdk_string_width( font
, text
.mbc_str() );
809 long height
= font
->ascent
+ font
->descent
;
810 gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() );
811 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height
);
812 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
814 gdk_draw_string( m_window
, font
, m_textGC
, x
, y
+ font
->ascent
, text
.mbc_str() );
816 /* CMB 17/7/98: simple underline: ignores scaling and underlying
817 X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS
818 properties (see wxXt implementation) */
819 if (m_font
.GetUnderlined())
821 long width
= gdk_string_width( font
, text
.mbc_str() );
822 long ul_y
= y
+ font
->ascent
;
823 if (font
->descent
> 0) ul_y
++;
824 gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x
+ width
, ul_y
);
828 GetTextExtent (text
, &w
, &h
);
829 CalcBoundingBox (x
+ w
, y
+ h
);
830 CalcBoundingBox (x
, y
);
833 bool wxWindowDC::CanGetTextExtent() const
838 void wxWindowDC::GetTextExtent( const wxString
&string
, long *width
, long *height
,
839 long *descent
, long *externalLeading
,
840 wxFont
*theFont
, bool WXUNUSED(use16
) )
842 wxFont fontToUse
= m_font
;
843 if (theFont
) fontToUse
= *theFont
;
845 GdkFont
*font
= fontToUse
.GetInternalFont( m_scaleY
);
846 if (width
) (*width
) = long(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
);
847 if (height
) (*height
) = long((font
->ascent
+ font
->descent
) / m_scaleY
);
848 if (descent
) (*descent
) = long(font
->descent
/ m_scaleY
);
849 if (externalLeading
) (*externalLeading
) = 0; // ??
852 long wxWindowDC::GetCharWidth()
854 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
855 return long(gdk_string_width( font
, "H" ) / m_scaleX
);
858 long wxWindowDC::GetCharHeight()
860 GdkFont
*font
= m_font
.GetInternalFont( m_scaleY
);
861 return long((font
->ascent
+ font
->descent
) / m_scaleY
);
864 void wxWindowDC::Clear()
866 wxCHECK_RET( Ok(), _T("invalid window dc") );
868 /* - we either are a memory dc or have a window as the
869 owner. anything else shouldn't happen.
870 - we don't use gdk_window_clear() as we don't set
871 the window's background colour anymore. it is too
872 much pain to keep the DC's and the window's back-
873 ground colour in synch. */
878 m_owner
->GetSize( &width
, &height
);
879 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
886 GetSize( &width
, &height
);
887 gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height
);
892 void wxWindowDC::SetFont( const wxFont
&font
)
897 void wxWindowDC::SetPen( const wxPen
&pen
)
899 wxCHECK_RET( Ok(), _T("invalid window dc") );
901 if (m_pen
== pen
) return;
905 if (!m_pen
.Ok()) return;
907 gint width
= m_pen
.GetWidth();
908 // CMB: if width is non-zero scale it with the dc
915 // X doesn't allow different width in x and y and so we take
917 double w
= 0.5 + (abs(XLOG2DEVREL(width
)) + abs(YLOG2DEVREL(width
))) / 2.0;
921 GdkLineStyle lineStyle
= GDK_LINE_SOLID
;
922 switch (m_pen
.GetStyle())
924 case wxSOLID
: { lineStyle
= GDK_LINE_SOLID
; break; }
925 case wxDOT
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
926 case wxLONG_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
927 case wxSHORT_DASH
: { lineStyle
= GDK_LINE_ON_OFF_DASH
; break; }
928 case wxDOT_DASH
: { lineStyle
= GDK_LINE_DOUBLE_DASH
; break; }
931 GdkCapStyle capStyle
= GDK_CAP_ROUND
;
932 switch (m_pen
.GetCap())
934 case wxCAP_ROUND
: { capStyle
= (width
<= 1) ? GDK_CAP_NOT_LAST
: GDK_CAP_ROUND
; break; }
935 case wxCAP_PROJECTING
: { capStyle
= GDK_CAP_PROJECTING
; break; }
936 case wxCAP_BUTT
: { capStyle
= GDK_CAP_BUTT
; break; }
939 GdkJoinStyle joinStyle
= GDK_JOIN_ROUND
;
940 switch (m_pen
.GetJoin())
942 case wxJOIN_BEVEL
: { joinStyle
= GDK_JOIN_BEVEL
; break; }
943 case wxJOIN_ROUND
: { joinStyle
= GDK_JOIN_ROUND
; break; }
944 case wxJOIN_MITER
: { joinStyle
= GDK_JOIN_MITER
; break; }
947 gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle
);
949 m_pen
.GetColour().CalcPixel( m_cmap
);
950 gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() );
953 void wxWindowDC::SetBrush( const wxBrush
&brush
)
955 wxCHECK_RET( Ok(), _T("invalid window dc") );
957 if (m_brush
== brush
) return;
961 if (!m_brush
.Ok()) return;
963 m_brush
.GetColour().CalcPixel( m_cmap
);
964 gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() );
966 GdkFill fillStyle
= GDK_SOLID
;
967 switch (m_brush
.GetStyle())
973 fillStyle
= GDK_STIPPLED
;
976 gdk_gc_set_fill( m_brushGC
, fillStyle
);
978 if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok()))
980 if (m_brush
.GetStipple()->GetPixmap())
981 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetPixmap() );
983 gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() );
986 if (IS_HATCH(m_brush
.GetStyle()))
988 int num
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
;
989 gdk_gc_set_stipple( m_brushGC
, hatches
[num
] );
993 void wxWindowDC::SetBackground( const wxBrush
&brush
)
995 /* CMB 21/7/98: Added SetBackground. Sets background brush
996 * for Clear() and bg colour for shapes filled with cross-hatch brush */
998 wxCHECK_RET( Ok(), _T("invalid window dc") );
1000 if (m_backgroundBrush
== brush
) return;
1002 m_backgroundBrush
= brush
;
1004 if (!m_backgroundBrush
.Ok()) return;
1006 m_backgroundBrush
.GetColour().CalcPixel( m_cmap
);
1007 gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() );
1008 gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() );
1009 gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1010 gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() );
1012 GdkFill fillStyle
= GDK_SOLID
;
1013 switch (m_backgroundBrush
.GetStyle())
1019 fillStyle
= GDK_STIPPLED
;
1022 gdk_gc_set_fill( m_bgGC
, fillStyle
);
1024 if (m_backgroundBrush
.GetStyle() == wxSTIPPLE
)
1026 gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() );
1029 if (IS_HATCH(m_backgroundBrush
.GetStyle()))
1031 int num
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
;
1032 gdk_gc_set_stipple( m_bgGC
, hatches
[num
] );
1036 void wxWindowDC::SetLogicalFunction( int function
)
1038 wxCHECK_RET( Ok(), _T("invalid window dc") );
1040 if (m_logicalFunction
== function
) return;
1042 GdkFunction mode
= GDK_COPY
;
1045 case wxXOR
: mode
= GDK_INVERT
; break;
1046 case wxINVERT
: mode
= GDK_INVERT
; break;
1047 #if (GDK_MINOR_VERSION > 0)
1048 case wxOR_REVERSE
: mode
= GDK_OR_REVERSE
; break;
1049 case wxAND_REVERSE
: mode
= GDK_AND_REVERSE
; break;
1050 case wxCLEAR
: mode
= GDK_CLEAR
; break;
1051 case wxSET
: mode
= GDK_SET
; break;
1052 case wxOR_INVERT
: mode
= GDK_OR_INVERT
; break;
1053 case wxAND
: mode
= GDK_AND
; break;
1054 case wxOR
: mode
= GDK_OR
; break;
1055 case wxEQUIV
: mode
= GDK_EQUIV
; break;
1056 case wxNAND
: mode
= GDK_NAND
; break;
1057 case wxAND_INVERT
: mode
= GDK_AND_INVERT
; break;
1058 /* ? wxSRC_INVERT GDK_AND_REVERSE, GDK_OR_REVERSE, GDK_OR_INVERT */
1063 m_logicalFunction
= function
;
1064 gdk_gc_set_function( m_penGC
, mode
);
1065 gdk_gc_set_function( m_brushGC
, mode
);
1066 gdk_gc_set_function( m_textGC
, mode
);
1069 void wxWindowDC::SetTextForeground( const wxColour
&col
)
1071 wxCHECK_RET( Ok(), _T("invalid window dc") );
1073 if (m_textForegroundColour
== col
) return;
1075 m_textForegroundColour
= col
;
1076 if (!m_textForegroundColour
.Ok()) return;
1078 m_textForegroundColour
.CalcPixel( m_cmap
);
1079 gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() );
1082 void wxWindowDC::SetTextBackground( const wxColour
&col
)
1084 wxCHECK_RET( Ok(), _T("invalid window dc") );
1086 if (m_textBackgroundColour
== col
) return;
1088 m_textBackgroundColour
= col
;
1089 if (!m_textBackgroundColour
.Ok()) return;
1091 m_textBackgroundColour
.CalcPixel( m_cmap
);
1092 gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() );
1095 void wxWindowDC::SetBackgroundMode( int mode
)
1097 wxCHECK_RET( Ok(), _T("invalid window dc") );
1099 m_backgroundMode
= mode
;
1101 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1102 // transparent/solid background mode
1104 if (m_brush
.GetStyle() != wxSOLID
&& m_brush
.GetStyle() != wxTRANSPARENT
)
1106 gdk_gc_set_fill( m_brushGC
,
1107 (m_backgroundMode
== wxTRANSPARENT
) ? GDK_STIPPLED
: GDK_OPAQUE_STIPPLED
);
1111 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) )
1113 wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") );
1116 void wxWindowDC::SetClippingRegion( long x
, long y
, long width
, long height
)
1118 wxCHECK_RET( Ok(), _T("invalid window dc") );
1120 wxDC::SetClippingRegion( x
, y
, width
, height
);
1123 rect
.x
= XLOG2DEV(x
);
1124 rect
.y
= YLOG2DEV(y
);
1125 rect
.width
= XLOG2DEVREL(width
);
1126 rect
.height
= YLOG2DEVREL(height
);
1127 gdk_gc_set_clip_rectangle( m_penGC
, &rect
);
1128 gdk_gc_set_clip_rectangle( m_brushGC
, &rect
);
1129 gdk_gc_set_clip_rectangle( m_textGC
, &rect
);
1130 gdk_gc_set_clip_rectangle( m_bgGC
, &rect
);
1133 void wxWindowDC::SetClippingRegion( const wxRegion
®ion
)
1135 wxCHECK_RET( Ok(), _T("invalid window dc") );
1139 DestroyClippingRegion();
1143 gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() );
1144 gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() );
1145 gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() );
1146 gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() );
1149 void wxWindowDC::DestroyClippingRegion()
1151 wxCHECK_RET( Ok(), _T("invalid window dc") );
1153 wxDC::DestroyClippingRegion();
1155 gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle
*) NULL
);
1156 gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle
*) NULL
);
1157 gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle
*) NULL
);
1158 gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle
*) NULL
);
1161 void wxWindowDC::SetUpDC()
1165 m_logicalFunction
= wxCOPY
;
1166 m_penGC
= gdk_gc_new( m_window
);
1167 m_brushGC
= gdk_gc_new( m_window
);
1168 m_textGC
= gdk_gc_new( m_window
);
1169 m_bgGC
= gdk_gc_new( m_window
);
1171 wxColour
tmp_col( m_textForegroundColour
);
1172 m_textForegroundColour
= wxNullColour
;
1173 SetTextForeground( tmp_col
);
1174 tmp_col
= m_textBackgroundColour
;
1175 m_textBackgroundColour
= wxNullColour
;
1176 SetTextBackground( tmp_col
);
1178 wxPen
tmp_pen( m_pen
);
1182 wxFont
tmp_font( m_font
);
1183 m_font
= wxNullFont
;
1184 SetFont( tmp_font
);
1186 wxBrush
tmp_brush( m_brush
);
1187 m_brush
= wxNullBrush
;
1188 SetBrush( tmp_brush
);
1190 tmp_brush
= m_backgroundBrush
;
1191 m_backgroundBrush
= wxNullBrush
;
1192 SetBackground( tmp_brush
);
1196 hatch_bitmap
= hatches
;
1197 hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height
);
1198 hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height
);
1199 hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height
);
1200 hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, cross_bits
, cross_width
, cross_height
);
1201 hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, horiz_bits
, horiz_width
, horiz_height
);
1202 hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow
*) NULL
, verti_bits
, verti_width
, verti_height
);
1206 void wxWindowDC::Destroy()
1208 if (m_penGC
) gdk_gc_unref( m_penGC
);
1209 m_penGC
= (GdkGC
*) NULL
;
1210 if (m_brushGC
) gdk_gc_unref( m_brushGC
);
1211 m_brushGC
= (GdkGC
*) NULL
;
1212 if (m_textGC
) gdk_gc_unref( m_textGC
);
1213 m_textGC
= (GdkGC
*) NULL
;
1214 if (m_bgGC
) gdk_gc_unref( m_bgGC
);
1215 m_bgGC
= (GdkGC
*) NULL
;
1218 GdkWindow
*wxWindowDC::GetWindow()
1223 // ----------------------------------- spline code ----------------------------------------
1225 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1226 double a3
, double b3
, double a4
, double b4
);
1227 void wx_clear_stack();
1228 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1229 double *y3
, double *x4
, double *y4
);
1230 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1231 double x4
, double y4
);
1232 static bool wx_spline_add_point(double x
, double y
);
1233 static void wx_spline_draw_point_array(wxDC
*dc
);
1235 wxList wx_spline_point_list
;
1237 #define half(z1, z2) ((z1+z2)/2.0)
1240 /* iterative version */
1242 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1245 register double xmid
, ymid
;
1246 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1249 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1251 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1252 xmid
= (double)half(x2
, x3
);
1253 ymid
= (double)half(y2
, y3
);
1254 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1255 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1256 wx_spline_add_point( x1
, y1
);
1257 wx_spline_add_point( xmid
, ymid
);
1259 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1260 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1261 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1262 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1267 /* utilities used by spline drawing routines */
1269 typedef struct wx_spline_stack_struct
{
1270 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1273 #define SPLINE_STACK_DEPTH 20
1274 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1275 static Stack
*wx_stack_top
;
1276 static int wx_stack_count
;
1278 void wx_clear_stack()
1280 wx_stack_top
= wx_spline_stack
;
1284 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1286 wx_stack_top
->x1
= x1
;
1287 wx_stack_top
->y1
= y1
;
1288 wx_stack_top
->x2
= x2
;
1289 wx_stack_top
->y2
= y2
;
1290 wx_stack_top
->x3
= x3
;
1291 wx_stack_top
->y3
= y3
;
1292 wx_stack_top
->x4
= x4
;
1293 wx_stack_top
->y4
= y4
;
1298 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1299 double *x3
, double *y3
, double *x4
, double *y4
)
1301 if (wx_stack_count
== 0)
1305 *x1
= wx_stack_top
->x1
;
1306 *y1
= wx_stack_top
->y1
;
1307 *x2
= wx_stack_top
->x2
;
1308 *y2
= wx_stack_top
->y2
;
1309 *x3
= wx_stack_top
->x3
;
1310 *y3
= wx_stack_top
->y3
;
1311 *x4
= wx_stack_top
->x4
;
1312 *y4
= wx_stack_top
->y4
;
1316 static bool wx_spline_add_point(double x
, double y
)
1318 wxPoint
*point
= new wxPoint
;
1321 wx_spline_point_list
.Append((wxObject
*)point
);
1325 static void wx_spline_draw_point_array(wxDC
*dc
)
1327 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
1328 wxNode
*node
= wx_spline_point_list
.First();
1331 wxPoint
*point
= (wxPoint
*)node
->Data();
1334 node
= wx_spline_point_list
.First();
1338 void wxWindowDC::DrawSpline( wxList
*points
)
1340 wxCHECK_RET( Ok(), _T("invalid window dc") );
1343 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1344 double x1
, y1
, x2
, y2
;
1346 wxNode
*node
= points
->First();
1347 p
= (wxPoint
*)node
->Data();
1352 node
= node
->Next();
1353 p
= (wxPoint
*)node
->Data();
1357 cx1
= (double)((x1
+ x2
) / 2);
1358 cy1
= (double)((y1
+ y2
) / 2);
1359 cx2
= (double)((cx1
+ x2
) / 2);
1360 cy2
= (double)((cy1
+ y2
) / 2);
1362 wx_spline_add_point(x1
, y1
);
1364 while ((node
= node
->Next()) != NULL
)
1366 p
= (wxPoint
*)node
->Data();
1371 cx4
= (double)(x1
+ x2
) / 2;
1372 cy4
= (double)(y1
+ y2
) / 2;
1373 cx3
= (double)(x1
+ cx4
) / 2;
1374 cy3
= (double)(y1
+ cy4
) / 2;
1376 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1380 cx2
= (double)(cx1
+ x2
) / 2;
1381 cy2
= (double)(cy1
+ y2
) / 2;
1384 wx_spline_add_point( cx1
, cy1
);
1385 wx_spline_add_point( x2
, y2
);
1387 wx_spline_draw_point_array( this );
1390 // Resolution in pixels per logical inch
1391 wxSize
wxWindowDC::GetPPI(void) const
1393 return wxSize(100, 100);
1396 //-----------------------------------------------------------------------------
1398 //-----------------------------------------------------------------------------
1400 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
)
1402 wxPaintDC::wxPaintDC()
1407 wxPaintDC::wxPaintDC( wxWindow
*win
)
1412 //-----------------------------------------------------------------------------
1414 //-----------------------------------------------------------------------------
1416 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
)
1418 wxClientDC::wxClientDC()
1423 wxClientDC::wxClientDC( wxWindow
*win
)