1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
21 #pragma implementation "dc.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
32 #include "wx/window.h"
35 #include "wx/dialog.h"
37 #include "wx/bitmap.h"
38 #include "wx/dcmemory.h"
43 #include "wx/dcprint.h"
48 #if wxUSE_COMMON_DIALOGS
56 #include "wx/msw/private.h"
58 #if !USE_SHARED_LIBRARY
59 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
62 // ---------------------------------------------------------------------------
64 // ---------------------------------------------------------------------------
66 static const int VIEWPORT_EXTENT
= 1000;
68 static const int MM_POINTS
= 9;
69 static const int MM_METRIC
= 10;
71 // ===========================================================================
73 // ===========================================================================
75 // ---------------------------------------------------------------------------
77 // ---------------------------------------------------------------------------
79 // Default constructor
93 m_windowExtX
= VIEWPORT_EXTENT
;
94 m_windowExtY
= VIEWPORT_EXTENT
;
103 SelectOldObjects(m_hDC
);
105 if ( m_canvas
== NULL
)
106 ::DeleteDC(GetHdc());
108 ::ReleaseDC((HWND
)m_canvas
->GetHWND(), GetHdc());
114 // This will select current objects out of the DC,
115 // which is what you have to do before deleting the
117 void wxDC::SelectOldObjects(WXHDC dc
)
123 ::SelectObject((HDC
) dc
, (HBITMAP
) m_oldBitmap
);
124 if (m_selectedBitmap
.Ok())
126 m_selectedBitmap
.SetSelectedInto(NULL
);
132 ::SelectObject((HDC
) dc
, (HPEN
) m_oldPen
);
137 ::SelectObject((HDC
) dc
, (HBRUSH
) m_oldBrush
);
142 ::SelectObject((HDC
) dc
, (HFONT
) m_oldFont
);
147 ::SelectPalette((HDC
) dc
, (HPALETTE
) m_oldPalette
, TRUE
);
152 m_brush
= wxNullBrush
;
154 m_palette
= wxNullPalette
;
156 m_backgroundBrush
= wxNullBrush
;
157 m_selectedBitmap
= wxNullBitmap
;
160 // ---------------------------------------------------------------------------
162 // ---------------------------------------------------------------------------
164 void wxDC::DoSetClippingRegion(long cx
, long cy
, long cw
, long ch
)
169 m_clipX2
= (int)(cx
+ cw
);
170 m_clipY2
= (int)(cy
+ ch
);
172 DoClipping((WXHDC
) m_hDC
);
175 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
177 wxCHECK_RET( region
.GetHRGN(), _T("invalid clipping region") );
179 wxRect box
= region
.GetBox();
184 m_clipX2
= box
.x
+ box
.width
;
185 m_clipY2
= box
.y
+ box
.height
;
188 SelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN());
190 ExtSelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN(), RGN_AND
);
194 void wxDC::DoClipping(WXHDC dc
)
196 if (m_clipping
&& dc
)
198 IntersectClipRect((HDC
) dc
, XLOG2DEV(m_clipX1
), YLOG2DEV(m_clipY1
),
199 XLOG2DEV(m_clipX2
), YLOG2DEV(m_clipY2
));
203 void wxDC::DestroyClippingRegion()
205 if (m_clipping
&& m_hDC
)
207 // TODO: this should restore the previous clipping region,
208 // so that OnPaint processing works correctly, and the update clipping region
209 // doesn't get destroyed after the first DestroyClippingRegion.
210 HRGN rgn
= CreateRectRgn(0, 0, 32000, 32000);
211 SelectClipRgn(GetHdc(), rgn
);
217 // ---------------------------------------------------------------------------
218 // query capabilities
219 // ---------------------------------------------------------------------------
221 bool wxDC::CanDrawBitmap() const
226 bool wxDC::CanGetTextExtent() const
228 // What sort of display is it?
229 int technology
= ::GetDeviceCaps(GetHdc(), TECHNOLOGY
);
231 return (technology
== DT_RASDISPLAY
) || (technology
== DT_RASPRINTER
);
234 int wxDC::GetDepth() const
236 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL
);
239 // ---------------------------------------------------------------------------
241 // ---------------------------------------------------------------------------
248 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
252 wxCHECK_RET( m_selectedBitmap
.Ok(), _T("this DC can't be cleared") );
254 rect
.left
= 0; rect
.top
= 0;
255 rect
.right
= m_selectedBitmap
.GetWidth();
256 rect
.bottom
= m_selectedBitmap
.GetHeight();
259 (void) ::SetMapMode(GetHdc(), MM_TEXT
);
261 DWORD colour
= GetBkColor(GetHdc());
262 HBRUSH brush
= CreateSolidBrush(colour
);
263 FillRect(GetHdc(), &rect
, brush
);
266 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
267 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
268 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
269 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
270 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
273 void wxDC::DoFloodFill(long x
, long y
, const wxColour
& col
, int style
)
275 (void)ExtFloodFill(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
277 style
== wxFLOOD_SURFACE
? FLOODFILLSURFACE
280 CalcBoundingBox(x
, y
);
283 bool wxDC::DoGetPixel(long x
, long y
, wxColour
*col
) const
285 // added by steve 29.12.94 (copied from DrawPoint)
286 // returns TRUE for pixels in the color of the current pen
287 // and FALSE for all other pixels colors
288 // if col is non-NULL return the color of the pixel
290 // get the color of the pixel
291 COLORREF pixelcolor
= ::GetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
));
292 // get the color of the pen
293 COLORREF pencolor
= 0x00ffffff;
296 pencolor
= m_pen
.GetColour().GetPixel();
299 // return the color of the pixel
301 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
303 // check, if color of the pixels is the same as the color
304 // of the current pen
305 return(pixelcolor
==pencolor
);
308 void wxDC::DoCrossHair(long x
, long y
)
310 long x1
= x
-VIEWPORT_EXTENT
;
311 long y1
= y
-VIEWPORT_EXTENT
;
312 long x2
= x
+VIEWPORT_EXTENT
;
313 long y2
= y
+VIEWPORT_EXTENT
;
315 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
316 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y
));
318 (void)MoveToEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
319 (void)LineTo(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y2
));
321 CalcBoundingBox(x1
, y1
);
322 CalcBoundingBox(x2
, y2
);
325 void wxDC::DoDrawLine(long x1
, long y1
, long x2
, long y2
)
327 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
328 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y2
));
330 /* MATTHEW: [6] New normalization */
331 #if WX_STANDARD_GRAPHICS
332 (void)LineTo(GetHdc(), XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
335 CalcBoundingBox(x1
, y1
);
336 CalcBoundingBox(x2
, y2
);
339 void wxDC::DoDrawArc(long x1
,long y1
,long x2
,long y2
, long xc
, long yc
)
343 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
344 if (x1
==x2
&& x2
==y2
)
346 DrawEllipse(xc
,yc
,(long)(radius
*2.0),(long)(radius
*2.0));
350 long xx1
= XLOG2DEV(x1
);
351 long yy1
= YLOG2DEV(y1
);
352 long xx2
= XLOG2DEV(x2
);
353 long yy2
= YLOG2DEV(y2
);
354 long xxc
= XLOG2DEV(xc
);
355 long yyc
= YLOG2DEV(yc
);
356 long ray
= (long) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
)));
358 (void)MoveToEx(GetHdc(), (int) xx1
, (int) yy1
, NULL
);
359 long xxx1
= (long) (xxc
-ray
);
360 long yyy1
= (long) (yyc
-ray
);
361 long xxx2
= (long) (xxc
+ray
);
362 long yyy2
= (long) (yyc
+ray
);
363 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
365 // Have to add 1 to bottom-right corner of rectangle
366 // to make semi-circles look right (crooked line otherwise).
367 // Unfortunately this is not a reliable method, depends
368 // on the size of shape.
369 // TODO: figure out why this happens!
370 Pie(GetHdc(),xxx1
,yyy1
,xxx2
+1,yyy2
+1,
374 Arc(GetHdc(),xxx1
,yyy1
,xxx2
,yyy2
,
377 CalcBoundingBox((xc
-radius
), (yc
-radius
));
378 CalcBoundingBox((xc
+radius
), (yc
+radius
));
381 void wxDC::DoDrawPoint(long x
, long y
)
383 COLORREF color
= 0x00ffffff;
386 color
= m_pen
.GetColour().GetPixel();
389 SetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), color
);
391 CalcBoundingBox(x
, y
);
394 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], long xoffset
, long yoffset
,int fillStyle
)
396 // Do things less efficiently if we have offsets
397 if (xoffset
!= 0 || yoffset
!= 0)
399 POINT
*cpoints
= new POINT
[n
];
401 for (i
= 0; i
< n
; i
++)
403 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
404 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
406 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
408 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
409 (void)Polygon(GetHdc(), cpoints
, n
);
410 SetPolyFillMode(GetHdc(),prev
);
416 for (i
= 0; i
< n
; i
++)
417 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
419 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
420 (void)Polygon(GetHdc(), (POINT
*) points
, n
);
421 SetPolyFillMode(GetHdc(),prev
);
425 void wxDC::DoDrawLines(int n
, wxPoint points
[], long xoffset
, long yoffset
)
427 // Do things less efficiently if we have offsets
428 if (xoffset
!= 0 || yoffset
!= 0)
430 POINT
*cpoints
= new POINT
[n
];
432 for (i
= 0; i
< n
; i
++)
434 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
435 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
437 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
439 (void)Polyline(GetHdc(), cpoints
, n
);
445 for (i
= 0; i
< n
; i
++)
446 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
448 (void)Polyline(GetHdc(), (POINT
*) points
, n
);
452 void wxDC::DoDrawRectangle(long x
, long y
, long width
, long height
)
455 long y2
= y
+ height
;
457 /* MATTHEW: [6] new normalization */
458 #if WX_STANDARD_GRAPHICS
459 bool do_brush
, do_pen
;
461 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
462 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
465 HPEN orig_pen
= NULL
;
467 if (do_pen
|| !m_pen
.Ok())
468 orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
470 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
471 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
473 if (do_pen
|| !m_pen
.Ok())
474 ::SelectObject(GetHdc() , orig_pen
);
477 HBRUSH orig_brush
= NULL
;
479 if (do_brush
|| !m_brush
.Ok())
480 orig_brush
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
482 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
483 XLOG2DEV(x2
), YLOG2DEV(y2
));
485 if (do_brush
|| !m_brush
.Ok())
486 ::SelectObject(GetHdc(), orig_brush
);
489 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
492 CalcBoundingBox(x
, y
);
493 CalcBoundingBox(x2
, y2
);
496 void wxDC::DoDrawRoundedRectangle(long x
, long y
, long width
, long height
, double radius
)
498 // Now, a negative radius value is interpreted to mean
499 // 'the proportion of the smallest X or Y dimension'
503 double smallest
= 0.0;
508 radius
= (- radius
* smallest
);
512 long y2
= (y
+height
);
514 (void)RoundRect(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
515 YLOG2DEV(y2
), (int) (2*XLOG2DEV(radius
)), (int)( 2*YLOG2DEV(radius
)));
517 CalcBoundingBox(x
, y
);
518 CalcBoundingBox(x2
, y2
);
521 void wxDC::DoDrawEllipse(long x
, long y
, long width
, long height
)
524 long y2
= (y
+height
);
526 (void)Ellipse(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
528 CalcBoundingBox(x
, y
);
529 CalcBoundingBox(x2
, y2
);
532 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
533 void wxDC::DoDrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
)
538 const double deg2rad
= 3.14159265359 / 180.0;
539 int rx1
= XLOG2DEV(x
+w
/2);
540 int ry1
= YLOG2DEV(y
+h
/2);
543 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
544 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
545 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
546 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
548 // draw pie with NULL_PEN first and then outline otherwise a line is
549 // drawn from the start and end points to the centre
550 HPEN orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
553 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
558 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
559 rx1
, ry1
-1, rx2
, ry2
-1);
561 ::SelectObject(GetHdc(), orig_pen
);
562 (void)Arc(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
565 CalcBoundingBox(x
, y
);
566 CalcBoundingBox(x2
, y2
);
569 void wxDC::DoDrawIcon(const wxIcon
& icon
, long x
, long y
)
571 #if defined(__WIN32__) && !defined(__SC__) && !defined(__TWIN32__)
572 ::DrawIconEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON(),
573 icon
.GetWidth(), icon
.GetHeight(), 0, 0, DI_NORMAL
);
575 ::DrawIcon(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
578 CalcBoundingBox(x
, y
);
579 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
582 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, long x
, long y
, bool useMask
)
587 // If we're not drawing transparently, and not drawing to a printer,
588 // optimize this function to use Windows functions.
589 if (!useMask
&& !IsKindOf(CLASSINFO(wxPrinterDC
)))
592 HDC memdc
= ::CreateCompatibleDC( cdc
);
593 HBITMAP hbitmap
= (HBITMAP
) bmp
.GetHBITMAP( );
595 wxASSERT_MSG( hbitmap
, _T("bitmap is ok but HBITMAP is NULL?") );
597 ::SelectObject( memdc
, hbitmap
);
598 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
603 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
605 memDC
.SelectObject(bmp
);
607 /* Not sure if we need this. The mask should leave the
608 * masked areas as per the original background of this DC.
611 // There might be transparent areas, so make these
612 // the same colour as this DC
613 memDC.SetBackground(* GetBackground());
617 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
619 memDC
.SelectObject(wxNullBitmap
);
623 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
625 if (m_textForegroundColour
.Ok())
626 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
628 DWORD old_background
= 0;
629 if (m_textBackgroundColour
.Ok())
631 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
634 if (m_backgroundMode
== wxTRANSPARENT
)
635 SetBkMode(GetHdc(), TRANSPARENT
);
637 SetBkMode(GetHdc(), OPAQUE
);
639 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), WXSTRINGCAST text
, wxStrlen(WXSTRINGCAST text
));
641 if (m_textBackgroundColour
.Ok())
642 (void)SetBkColor(GetHdc(), old_background
);
644 // background colour is used only for DrawText, otherwise
645 // always TRANSPARENT, RR
646 SetBkMode(GetHdc(), TRANSPARENT
);
648 CalcBoundingBox(x
, y
);
651 GetTextExtent(text
, &w
, &h
);
652 CalcBoundingBox((x
+ w
), (y
+ h
));
655 // ---------------------------------------------------------------------------
657 // ---------------------------------------------------------------------------
659 void wxDC::SetPalette(const wxPalette
& palette
)
661 // Set the old object temporarily, in case the assignment deletes an object
662 // that's not yet selected out.
665 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
673 // Setting a NULL colourmap is a way of restoring
674 // the original colourmap
677 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
684 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
686 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
688 m_oldPalette
= (WXHPALETTE
) oldPal
;
690 ::RealizePalette(GetHdc());
694 void wxDC::SetFont(const wxFont
& the_font
)
696 // Set the old object temporarily, in case the assignment deletes an object
697 // that's not yet selected out.
700 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
709 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
713 if (m_font
.Ok() && m_font
.GetResourceHandle())
715 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
716 if (f
== (HFONT
) NULL
)
718 wxLogDebug(_T("::SelectObject failed in wxDC::SetFont."));
721 m_oldFont
= (WXHFONT
) f
;
725 void wxDC::SetPen(const wxPen
& pen
)
727 // Set the old object temporarily, in case the assignment deletes an object
728 // that's not yet selected out.
731 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
740 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
746 if (m_pen
.GetResourceHandle())
748 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
750 m_oldPen
= (WXHPEN
) p
;
755 void wxDC::SetBrush(const wxBrush
& brush
)
757 // Set the old object temporarily, in case the assignment deletes an object
758 // that's not yet selected out.
761 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
770 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
776 if (m_brush
.GetResourceHandle())
779 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
781 m_oldBrush
= (WXHBRUSH
) b
;
786 void wxDC::SetBackground(const wxBrush
& brush
)
788 m_backgroundBrush
= brush
;
790 if (!m_backgroundBrush
.Ok())
795 bool customColours
= TRUE
;
796 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
797 // change background colours from the control-panel specified colours.
798 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
799 customColours
= FALSE
;
803 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
805 m_canvas
->SetTransparent(TRUE
);
809 // New behaviour, 10/2/99: setting the background brush of a DC
810 // doesn't affect the window background colour. However,
811 // I'm leaving in the transparency setting because it's needed by
812 // various controls (e.g. wxStaticText) to determine whether to draw
813 // transparently or not. TODO: maybe this should be a new function
814 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
816 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
817 m_canvas
->SetTransparent(FALSE
);
821 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
823 (void)SetBkColor(GetHdc(), new_color
);
827 void wxDC::SetBackgroundMode(int mode
)
829 m_backgroundMode
= mode
;
831 // SetBackgroundColour now only refers to text background
832 // and m_backgroundMode is used there
835 if (m_backgroundMode == wxTRANSPARENT)
836 ::SetBkMode(GetHdc(), TRANSPARENT);
838 ::SetBkMode(GetHdc(), OPAQUE);
842 void wxDC::SetLogicalFunction(int function
)
844 m_logicalFunction
= function
;
846 SetRop((WXHDC
) m_hDC
);
849 void wxDC::SetRop(WXHDC dc
)
851 if (!dc
|| m_logicalFunction
< 0)
855 // These may be wrong
856 switch (m_logicalFunction
)
858 // case wxXOR: c_rop = R2_XORPEN; break;
859 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
860 case wxINVERT
: c_rop
= R2_NOT
; break;
861 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
862 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
863 case wxCLEAR
: c_rop
= R2_WHITE
; break;
864 case wxSET
: c_rop
= R2_BLACK
; break;
865 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
866 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
867 case wxAND
: c_rop
= R2_MASKPEN
; break;
868 case wxOR
: c_rop
= R2_MERGEPEN
; break;
869 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
874 c_rop
= R2_COPYPEN
; break;
876 SetROP2((HDC
) dc
, c_rop
);
879 bool wxDC::StartDoc(const wxString
& message
)
881 // We might be previewing, so return TRUE to let it continue.
889 void wxDC::StartPage()
897 // ---------------------------------------------------------------------------
899 // ---------------------------------------------------------------------------
901 long wxDC::GetCharHeight() const
903 TEXTMETRIC lpTextMetric
;
905 GetTextMetrics(GetHdc(), &lpTextMetric
);
907 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
910 long wxDC::GetCharWidth() const
912 TEXTMETRIC lpTextMetric
;
914 GetTextMetrics(GetHdc(), &lpTextMetric
);
916 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
919 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
920 long *descent
, long *externalLeading
,
921 wxFont
*theFont
) const
923 wxFont
*fontToUse
= (wxFont
*) theFont
;
925 fontToUse
= (wxFont
*) &m_font
;
930 GetTextExtentPoint(GetHdc(), WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
931 GetTextMetrics(GetHdc(), &tm
);
933 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
934 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
935 if (descent
) *descent
= tm
.tmDescent
;
936 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
939 void wxDC::SetMapMode(int mode
)
941 m_mappingMode
= mode
;
944 int pixel_height
= 0;
948 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
949 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
950 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
951 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
953 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
958 double mm2pixelsX
= pixel_width
/mm_width
;
959 double mm2pixelsY
= pixel_height
/mm_height
;
965 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
966 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
971 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
972 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
977 m_logicalScaleX
= mm2pixelsX
;
978 m_logicalScaleY
= mm2pixelsY
;
983 m_logicalScaleX
= (mm2pixelsX
/10.0);
984 m_logicalScaleY
= (mm2pixelsY
/10.0);
990 m_logicalScaleX
= 1.0;
991 m_logicalScaleY
= 1.0;
996 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
997 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
999 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1000 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1001 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1002 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1003 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1004 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1007 void wxDC::SetUserScale(double x
, double y
)
1012 SetMapMode(m_mappingMode
);
1015 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1017 m_signX
= xLeftRight
? 1 : -1;
1018 m_signY
= yBottomUp
? -1 : 1;
1020 SetMapMode(m_mappingMode
);
1023 void wxDC::SetSystemScale(double x
, double y
)
1028 SetMapMode(m_mappingMode
);
1031 void wxDC::SetLogicalOrigin(long x
, long y
)
1033 m_logicalOriginX
= x
;
1034 m_logicalOriginY
= y
;
1036 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1039 void wxDC::SetDeviceOrigin(long x
, long y
)
1041 m_deviceOriginX
= x
;
1042 m_deviceOriginY
= y
;
1044 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1047 // ---------------------------------------------------------------------------
1048 // coordinates transformations
1049 // ---------------------------------------------------------------------------
1051 long wxDCBase::DeviceToLogicalX(long x
) const
1053 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1056 long wxDCBase::DeviceToLogicalXRel(long x
) const
1058 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1061 long wxDCBase::DeviceToLogicalY(long y
) const
1063 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1066 long wxDCBase::DeviceToLogicalYRel(long y
) const
1068 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1071 long wxDCBase::LogicalToDeviceX(long x
) const
1073 return (long) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1076 long wxDCBase::LogicalToDeviceXRel(long x
) const
1078 return (long) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1081 long wxDCBase::LogicalToDeviceY(long y
) const
1083 return (long) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1086 long wxDCBase::LogicalToDeviceYRel(long y
) const
1088 return (long) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1091 // ---------------------------------------------------------------------------
1093 // ---------------------------------------------------------------------------
1094 bool wxDC::DoBlit(long xdest
, long ydest
, long width
, long height
,
1095 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1097 long xdest1
= xdest
;
1098 long ydest1
= ydest
;
1102 // Chris Breeze 18/5/98: use text foreground/background colours
1103 // when blitting from 1-bit bitmaps
1104 COLORREF old_textground
= ::GetTextColor(GetHdc());
1105 COLORREF old_background
= ::GetBkColor(GetHdc());
1106 if (m_textForegroundColour
.Ok())
1108 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1110 if (m_textBackgroundColour
.Ok())
1112 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1115 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1116 rop
== wxCLEAR
? WHITENESS
:
1117 rop
== wxSET
? BLACKNESS
:
1118 rop
== wxINVERT
? DSTINVERT
:
1119 rop
== wxAND
? MERGECOPY
:
1120 rop
== wxOR
? MERGEPAINT
:
1121 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1122 rop
== wxXOR
? SRCINVERT
:
1123 rop
== wxOR_REVERSE
? MERGEPAINT
:
1124 rop
== wxAND_REVERSE
? SRCERASE
:
1125 rop
== wxSRC_OR
? SRCPAINT
:
1126 rop
== wxSRC_AND
? SRCAND
:
1129 bool success
= TRUE
;
1130 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1134 // Not implemented under Win95 (or maybe a specific device?)
1135 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1136 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1146 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1147 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1148 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1149 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1150 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1151 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1152 ::SelectObject(dc_mask
, 0);
1153 ::DeleteDC(dc_mask
);
1155 // New code from Chris Breeze, 15/7/98
1156 // Blit bitmap with mask
1158 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1160 // If we are printing source colours are screen colours
1161 // not printer colours and so we need copy the bitmap
1164 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1165 HDC dc_src
= (HDC
) source
->m_hDC
;
1167 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1168 for (int x
= 0; x
< width
; x
++)
1170 for (int y
= 0; y
< height
; y
++)
1172 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1175 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1176 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1177 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1178 ::FillRect(GetHdc(), &rect
, brush
);
1179 ::DeleteObject(brush
);
1183 ::SelectObject(dc_mask
, 0);
1184 ::DeleteDC(dc_mask
);
1188 // create a temp buffer bitmap and DCs to access it and the mask
1189 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1190 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1191 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1192 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1193 ::SelectObject(dc_buffer
, buffer_bmap
);
1195 // copy dest to buffer
1196 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1197 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1199 // copy src to buffer using selected raster op
1200 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1201 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1203 // set masked area in buffer to BLACK (pixel value 0)
1204 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1205 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1206 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1207 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1209 // set unmasked area in dest to BLACK
1210 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1211 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1212 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1213 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1214 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1215 ::SetTextColor(GetHdc(), prevCol
);
1217 // OR buffer to dest
1218 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1219 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1221 // tidy up temporary DCs and bitmap
1222 ::SelectObject(dc_mask
, 0);
1223 ::DeleteDC(dc_mask
);
1224 ::SelectObject(dc_buffer
, 0);
1225 ::DeleteDC(dc_buffer
);
1226 ::DeleteObject(buffer_bmap
);
1232 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1234 // If we are printing, source colours are screen colours
1235 // not printer colours and so we need copy the bitmap
1237 HDC dc_src
= (HDC
) source
->m_hDC
;
1239 for (int x
= 0; x
< width
; x
++)
1241 for (int y
= 0; y
< height
; y
++)
1243 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1244 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1245 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1246 ::FillRect(GetHdc(), &rect
, brush
);
1247 ::DeleteObject(brush
);
1253 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1254 xsrc1
, ysrc1
, dwRop
) != 0);
1257 ::SetTextColor(GetHdc(), old_textground
);
1258 ::SetBkColor(GetHdc(), old_background
);
1263 void wxDC::DoGetSize(int *w
, int *h
) const
1265 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1266 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1269 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1271 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1272 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1275 wxSize
wxDC::GetPPI() const
1277 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1278 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1280 return wxSize(x
, y
);
1283 // For use by wxWindows only, unless custom units are required.
1284 void wxDC::SetLogicalScale(double x
, double y
)
1286 m_logicalScaleX
= x
;
1287 m_logicalScaleY
= y
;
1290 #if WXWIN_COMPATIBILITY
1291 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1292 float *descent
, float *externalLeading
,
1293 wxFont
*theFont
, bool use16bit
) const
1295 long x1
, y1
, descent1
, externalLeading1
;
1296 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1299 *descent
= descent1
;
1300 if (externalLeading
)
1301 *externalLeading
= externalLeading1
;
1305 // ---------------------------------------------------------------------------
1306 // spline drawing code
1307 // ---------------------------------------------------------------------------
1311 class wxSpline
: public wxObject
1317 wxSpline(wxList
*list
);
1318 void DeletePoints();
1320 // Doesn't delete points
1324 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1326 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1327 double a3
, double b3
, double a4
, double b4
);
1328 void wx_clear_stack();
1329 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1330 double *y3
, double *x4
, double *y4
);
1331 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1332 double x4
, double y4
);
1333 static bool wx_spline_add_point(double x
, double y
);
1334 static void wx_spline_draw_point_array(wxDC
*dc
);
1335 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1337 void wxDC::DoDrawSpline(wxList
*list
)
1339 wxSpline
spline(list
);
1341 wx_draw_open_spline(this, &spline
);
1344 wxList wx_spline_point_list
;
1346 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1349 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1350 double x1
, y1
, x2
, y2
;
1352 wxNode
*node
= spline
->points
->First();
1353 p
= (wxPoint
*)node
->Data();
1358 node
= node
->Next();
1359 p
= (wxPoint
*)node
->Data();
1363 cx1
= (double)((x1
+ x2
) / 2);
1364 cy1
= (double)((y1
+ y2
) / 2);
1365 cx2
= (double)((cx1
+ x2
) / 2);
1366 cy2
= (double)((cy1
+ y2
) / 2);
1368 wx_spline_add_point(x1
, y1
);
1370 while ((node
= node
->Next()) != NULL
)
1372 p
= (wxPoint
*)node
->Data();
1377 cx4
= (double)(x1
+ x2
) / 2;
1378 cy4
= (double)(y1
+ y2
) / 2;
1379 cx3
= (double)(x1
+ cx4
) / 2;
1380 cy3
= (double)(y1
+ cy4
) / 2;
1382 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1386 cx2
= (double)(cx1
+ x2
) / 2;
1387 cy2
= (double)(cy1
+ y2
) / 2;
1390 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1391 wx_spline_add_point(x2
, y2
);
1393 wx_spline_draw_point_array(dc
);
1397 /********************* CURVES FOR SPLINES *****************************
1399 The following spline drawing routine is from
1401 "An Algorithm for High-Speed Curve Generation"
1402 by George Merrill Chaikin,
1403 Computer Graphics and Image Processing, 3, Academic Press,
1408 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1409 Computer Graphics and Image Processing, 4, Academic Press,
1412 ***********************************************************************/
1414 #define half(z1, z2) ((z1+z2)/2.0)
1417 /* iterative version */
1419 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1422 register double xmid
, ymid
;
1423 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1426 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1428 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1429 xmid
= (double)half(x2
, x3
);
1430 ymid
= (double)half(y2
, y3
);
1431 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1432 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1433 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1434 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1436 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1437 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1438 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1439 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1445 /* utilities used by spline drawing routines */
1448 typedef struct wx_spline_stack_struct
{
1449 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1453 #define SPLINE_STACK_DEPTH 20
1454 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1455 static Stack
*wx_stack_top
;
1456 static int wx_stack_count
;
1458 void wx_clear_stack()
1460 wx_stack_top
= wx_spline_stack
;
1464 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1466 wx_stack_top
->x1
= x1
;
1467 wx_stack_top
->y1
= y1
;
1468 wx_stack_top
->x2
= x2
;
1469 wx_stack_top
->y2
= y2
;
1470 wx_stack_top
->x3
= x3
;
1471 wx_stack_top
->y3
= y3
;
1472 wx_stack_top
->x4
= x4
;
1473 wx_stack_top
->y4
= y4
;
1478 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1479 double *x3
, double *y3
, double *x4
, double *y4
)
1481 if (wx_stack_count
== 0)
1485 *x1
= wx_stack_top
->x1
;
1486 *y1
= wx_stack_top
->y1
;
1487 *x2
= wx_stack_top
->x2
;
1488 *y2
= wx_stack_top
->y2
;
1489 *x3
= wx_stack_top
->x3
;
1490 *y3
= wx_stack_top
->y3
;
1491 *x4
= wx_stack_top
->x4
;
1492 *y4
= wx_stack_top
->y4
;
1496 static bool wx_spline_add_point(double x
, double y
)
1498 wxPoint
*point
= new wxPoint
;
1501 wx_spline_point_list
.Append((wxObject
*)point
);
1505 static void wx_spline_draw_point_array(wxDC
*dc
)
1507 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1508 wxNode
*node
= wx_spline_point_list
.First();
1511 wxPoint
*point
= (wxPoint
*)node
->Data();
1514 node
= wx_spline_point_list
.First();
1518 wxSpline::wxSpline(wxList
*list
)
1523 wxSpline::~wxSpline()
1527 void wxSpline::DeletePoints()
1529 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1531 wxPoint
*point
= (wxPoint
*)node
->Data();
1539 #endif // wxUSE_SPLINES