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( );
594 ::SelectObject( memdc
, hbitmap
);
595 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
600 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
602 memDC
.SelectObject(bmp
);
604 /* Not sure if we need this. The mask should leave the
605 * masked areas as per the original background of this DC.
608 // There might be transparent areas, so make these
609 // the same colour as this DC
610 memDC.SetBackground(* GetBackground());
614 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
616 memDC
.SelectObject(wxNullBitmap
);
620 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
622 if (m_textForegroundColour
.Ok())
623 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
625 DWORD old_background
= 0;
626 if (m_textBackgroundColour
.Ok())
628 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
631 if (m_backgroundMode
== wxTRANSPARENT
)
632 SetBkMode(GetHdc(), TRANSPARENT
);
634 SetBkMode(GetHdc(), OPAQUE
);
636 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), WXSTRINGCAST text
, wxStrlen(WXSTRINGCAST text
));
638 if (m_textBackgroundColour
.Ok())
639 (void)SetBkColor(GetHdc(), old_background
);
641 // background colour is used only for DrawText, otherwise
642 // always TRANSPARENT, RR
643 SetBkMode(GetHdc(), TRANSPARENT
);
645 CalcBoundingBox(x
, y
);
648 GetTextExtent(text
, &w
, &h
);
649 CalcBoundingBox((x
+ w
), (y
+ h
));
652 // ---------------------------------------------------------------------------
654 // ---------------------------------------------------------------------------
656 void wxDC::SetPalette(const wxPalette
& palette
)
658 // Set the old object temporarily, in case the assignment deletes an object
659 // that's not yet selected out.
662 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
670 // Setting a NULL colourmap is a way of restoring
671 // the original colourmap
674 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
681 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
683 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
685 m_oldPalette
= (WXHPALETTE
) oldPal
;
687 ::RealizePalette(GetHdc());
691 void wxDC::SetFont(const wxFont
& the_font
)
693 // Set the old object temporarily, in case the assignment deletes an object
694 // that's not yet selected out.
697 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
706 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
710 if (m_font
.Ok() && m_font
.GetResourceHandle())
712 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
713 if (f
== (HFONT
) NULL
)
715 wxLogDebug(_T("::SelectObject failed in wxDC::SetFont."));
718 m_oldFont
= (WXHFONT
) f
;
722 void wxDC::SetPen(const wxPen
& pen
)
724 // Set the old object temporarily, in case the assignment deletes an object
725 // that's not yet selected out.
728 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
737 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
743 if (m_pen
.GetResourceHandle())
745 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
747 m_oldPen
= (WXHPEN
) p
;
752 void wxDC::SetBrush(const wxBrush
& brush
)
754 // Set the old object temporarily, in case the assignment deletes an object
755 // that's not yet selected out.
758 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
767 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
773 if (m_brush
.GetResourceHandle())
776 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
778 m_oldBrush
= (WXHBRUSH
) b
;
783 void wxDC::SetBackground(const wxBrush
& brush
)
785 m_backgroundBrush
= brush
;
787 if (!m_backgroundBrush
.Ok())
792 bool customColours
= TRUE
;
793 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
794 // change background colours from the control-panel specified colours.
795 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
796 customColours
= FALSE
;
800 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
802 m_canvas
->SetTransparent(TRUE
);
806 // New behaviour, 10/2/99: setting the background brush of a DC
807 // doesn't affect the window background colour. However,
808 // I'm leaving in the transparency setting because it's needed by
809 // various controls (e.g. wxStaticText) to determine whether to draw
810 // transparently or not. TODO: maybe this should be a new function
811 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
813 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
814 m_canvas
->SetTransparent(FALSE
);
818 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
820 (void)SetBkColor(GetHdc(), new_color
);
824 void wxDC::SetBackgroundMode(int mode
)
826 m_backgroundMode
= mode
;
828 // SetBackgroundColour now only refers to text background
829 // and m_backgroundMode is used there
832 if (m_backgroundMode == wxTRANSPARENT)
833 ::SetBkMode(GetHdc(), TRANSPARENT);
835 ::SetBkMode(GetHdc(), OPAQUE);
839 void wxDC::SetLogicalFunction(int function
)
841 m_logicalFunction
= function
;
843 SetRop((WXHDC
) m_hDC
);
846 void wxDC::SetRop(WXHDC dc
)
848 if (!dc
|| m_logicalFunction
< 0)
852 // These may be wrong
853 switch (m_logicalFunction
)
855 // case wxXOR: c_rop = R2_XORPEN; break;
856 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
857 case wxINVERT
: c_rop
= R2_NOT
; break;
858 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
859 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
860 case wxCLEAR
: c_rop
= R2_WHITE
; break;
861 case wxSET
: c_rop
= R2_BLACK
; break;
862 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
863 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
864 case wxAND
: c_rop
= R2_MASKPEN
; break;
865 case wxOR
: c_rop
= R2_MERGEPEN
; break;
866 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
871 c_rop
= R2_COPYPEN
; break;
873 SetROP2((HDC
) dc
, c_rop
);
876 bool wxDC::StartDoc(const wxString
& message
)
878 // We might be previewing, so return TRUE to let it continue.
886 void wxDC::StartPage()
894 // ---------------------------------------------------------------------------
896 // ---------------------------------------------------------------------------
898 long wxDC::GetCharHeight() const
900 TEXTMETRIC lpTextMetric
;
902 GetTextMetrics(GetHdc(), &lpTextMetric
);
904 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
907 long wxDC::GetCharWidth() const
909 TEXTMETRIC lpTextMetric
;
911 GetTextMetrics(GetHdc(), &lpTextMetric
);
913 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
916 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
917 long *descent
, long *externalLeading
,
918 wxFont
*theFont
) const
920 wxFont
*fontToUse
= (wxFont
*) theFont
;
922 fontToUse
= (wxFont
*) &m_font
;
927 GetTextExtentPoint(GetHdc(), WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
928 GetTextMetrics(GetHdc(), &tm
);
930 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
931 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
932 if (descent
) *descent
= tm
.tmDescent
;
933 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
936 void wxDC::SetMapMode(int mode
)
938 m_mappingMode
= mode
;
941 int pixel_height
= 0;
945 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
946 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
947 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
948 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
950 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
955 double mm2pixelsX
= pixel_width
/mm_width
;
956 double mm2pixelsY
= pixel_height
/mm_height
;
962 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
963 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
968 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
969 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
974 m_logicalScaleX
= mm2pixelsX
;
975 m_logicalScaleY
= mm2pixelsY
;
980 m_logicalScaleX
= (mm2pixelsX
/10.0);
981 m_logicalScaleY
= (mm2pixelsY
/10.0);
987 m_logicalScaleX
= 1.0;
988 m_logicalScaleY
= 1.0;
993 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
994 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
996 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
997 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
998 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
999 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1000 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1001 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1004 void wxDC::SetUserScale(double x
, double y
)
1009 SetMapMode(m_mappingMode
);
1012 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1014 m_signX
= xLeftRight
? 1 : -1;
1015 m_signY
= yBottomUp
? -1 : 1;
1017 SetMapMode(m_mappingMode
);
1020 void wxDC::SetSystemScale(double x
, double y
)
1025 SetMapMode(m_mappingMode
);
1028 void wxDC::SetLogicalOrigin(long x
, long y
)
1030 m_logicalOriginX
= x
;
1031 m_logicalOriginY
= y
;
1033 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1036 void wxDC::SetDeviceOrigin(long x
, long y
)
1038 m_deviceOriginX
= x
;
1039 m_deviceOriginY
= y
;
1041 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1044 // ---------------------------------------------------------------------------
1045 // coordinates transformations
1046 // ---------------------------------------------------------------------------
1048 long wxDCBase::DeviceToLogicalX(long x
) const
1050 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1053 long wxDCBase::DeviceToLogicalXRel(long x
) const
1055 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1058 long wxDCBase::DeviceToLogicalY(long y
) const
1060 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1063 long wxDCBase::DeviceToLogicalYRel(long y
) const
1065 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1068 long wxDCBase::LogicalToDeviceX(long x
) const
1070 return (long) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1073 long wxDCBase::LogicalToDeviceXRel(long x
) const
1075 return (long) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1078 long wxDCBase::LogicalToDeviceY(long y
) const
1080 return (long) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1083 long wxDCBase::LogicalToDeviceYRel(long y
) const
1085 return (long) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1088 // ---------------------------------------------------------------------------
1090 // ---------------------------------------------------------------------------
1091 bool wxDC::DoBlit(long xdest
, long ydest
, long width
, long height
,
1092 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1094 long xdest1
= xdest
;
1095 long ydest1
= ydest
;
1099 // Chris Breeze 18/5/98: use text foreground/background colours
1100 // when blitting from 1-bit bitmaps
1101 COLORREF old_textground
= ::GetTextColor(GetHdc());
1102 COLORREF old_background
= ::GetBkColor(GetHdc());
1103 if (m_textForegroundColour
.Ok())
1105 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1107 if (m_textBackgroundColour
.Ok())
1109 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1112 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1113 rop
== wxCLEAR
? WHITENESS
:
1114 rop
== wxSET
? BLACKNESS
:
1115 rop
== wxINVERT
? DSTINVERT
:
1116 rop
== wxAND
? MERGECOPY
:
1117 rop
== wxOR
? MERGEPAINT
:
1118 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1119 rop
== wxXOR
? SRCINVERT
:
1120 rop
== wxOR_REVERSE
? MERGEPAINT
:
1121 rop
== wxAND_REVERSE
? SRCERASE
:
1122 rop
== wxSRC_OR
? SRCPAINT
:
1123 rop
== wxSRC_AND
? SRCAND
:
1126 bool success
= TRUE
;
1127 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1131 // Not implemented under Win95 (or maybe a specific device?)
1132 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1133 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1143 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1144 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1145 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1146 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1147 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1148 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1149 ::SelectObject(dc_mask
, 0);
1150 ::DeleteDC(dc_mask
);
1152 // New code from Chris Breeze, 15/7/98
1153 // Blit bitmap with mask
1155 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1157 // If we are printing source colours are screen colours
1158 // not printer colours and so we need copy the bitmap
1161 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1162 HDC dc_src
= (HDC
) source
->m_hDC
;
1164 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1165 for (int x
= 0; x
< width
; x
++)
1167 for (int y
= 0; y
< height
; y
++)
1169 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1172 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1173 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1174 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1175 ::FillRect(GetHdc(), &rect
, brush
);
1176 ::DeleteObject(brush
);
1180 ::SelectObject(dc_mask
, 0);
1181 ::DeleteDC(dc_mask
);
1185 // create a temp buffer bitmap and DCs to access it and the mask
1186 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1187 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1188 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1189 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1190 ::SelectObject(dc_buffer
, buffer_bmap
);
1192 // copy dest to buffer
1193 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1194 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1196 // copy src to buffer using selected raster op
1197 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1198 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1200 // set masked area in buffer to BLACK (pixel value 0)
1201 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1202 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1203 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1204 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1206 // set unmasked area in dest to BLACK
1207 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1208 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1209 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1210 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1211 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1212 ::SetTextColor(GetHdc(), prevCol
);
1214 // OR buffer to dest
1215 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1216 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1218 // tidy up temporary DCs and bitmap
1219 ::SelectObject(dc_mask
, 0);
1220 ::DeleteDC(dc_mask
);
1221 ::SelectObject(dc_buffer
, 0);
1222 ::DeleteDC(dc_buffer
);
1223 ::DeleteObject(buffer_bmap
);
1229 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1231 // If we are printing, source colours are screen colours
1232 // not printer colours and so we need copy the bitmap
1234 HDC dc_src
= (HDC
) source
->m_hDC
;
1236 for (int x
= 0; x
< width
; x
++)
1238 for (int y
= 0; y
< height
; y
++)
1240 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1241 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1242 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1243 ::FillRect(GetHdc(), &rect
, brush
);
1244 ::DeleteObject(brush
);
1250 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1251 xsrc1
, ysrc1
, dwRop
) != 0);
1254 ::SetTextColor(GetHdc(), old_textground
);
1255 ::SetBkColor(GetHdc(), old_background
);
1260 void wxDC::DoGetSize(int *w
, int *h
) const
1262 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1263 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1266 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1268 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1269 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1272 wxSize
wxDC::GetPPI() const
1274 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1275 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1277 return wxSize(x
, y
);
1280 // For use by wxWindows only, unless custom units are required.
1281 void wxDC::SetLogicalScale(double x
, double y
)
1283 m_logicalScaleX
= x
;
1284 m_logicalScaleY
= y
;
1287 #if WXWIN_COMPATIBILITY
1288 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1289 float *descent
, float *externalLeading
,
1290 wxFont
*theFont
, bool use16bit
) const
1292 long x1
, y1
, descent1
, externalLeading1
;
1293 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1296 *descent
= descent1
;
1297 if (externalLeading
)
1298 *externalLeading
= externalLeading1
;
1302 // ---------------------------------------------------------------------------
1303 // spline drawing code
1304 // ---------------------------------------------------------------------------
1308 class wxSpline
: public wxObject
1314 wxSpline(wxList
*list
);
1315 void DeletePoints();
1317 // Doesn't delete points
1321 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1323 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1324 double a3
, double b3
, double a4
, double b4
);
1325 void wx_clear_stack();
1326 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1327 double *y3
, double *x4
, double *y4
);
1328 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1329 double x4
, double y4
);
1330 static bool wx_spline_add_point(double x
, double y
);
1331 static void wx_spline_draw_point_array(wxDC
*dc
);
1332 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1334 void wxDC::DoDrawSpline(wxList
*list
)
1336 wxSpline
spline(list
);
1338 wx_draw_open_spline(this, &spline
);
1341 wxList wx_spline_point_list
;
1343 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1346 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1347 double x1
, y1
, x2
, y2
;
1349 wxNode
*node
= spline
->points
->First();
1350 p
= (wxPoint
*)node
->Data();
1355 node
= node
->Next();
1356 p
= (wxPoint
*)node
->Data();
1360 cx1
= (double)((x1
+ x2
) / 2);
1361 cy1
= (double)((y1
+ y2
) / 2);
1362 cx2
= (double)((cx1
+ x2
) / 2);
1363 cy2
= (double)((cy1
+ y2
) / 2);
1365 wx_spline_add_point(x1
, y1
);
1367 while ((node
= node
->Next()) != NULL
)
1369 p
= (wxPoint
*)node
->Data();
1374 cx4
= (double)(x1
+ x2
) / 2;
1375 cy4
= (double)(y1
+ y2
) / 2;
1376 cx3
= (double)(x1
+ cx4
) / 2;
1377 cy3
= (double)(y1
+ cy4
) / 2;
1379 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1383 cx2
= (double)(cx1
+ x2
) / 2;
1384 cy2
= (double)(cy1
+ y2
) / 2;
1387 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1388 wx_spline_add_point(x2
, y2
);
1390 wx_spline_draw_point_array(dc
);
1394 /********************* CURVES FOR SPLINES *****************************
1396 The following spline drawing routine is from
1398 "An Algorithm for High-Speed Curve Generation"
1399 by George Merrill Chaikin,
1400 Computer Graphics and Image Processing, 3, Academic Press,
1405 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1406 Computer Graphics and Image Processing, 4, Academic Press,
1409 ***********************************************************************/
1411 #define half(z1, z2) ((z1+z2)/2.0)
1414 /* iterative version */
1416 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1419 register double xmid
, ymid
;
1420 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1423 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1425 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1426 xmid
= (double)half(x2
, x3
);
1427 ymid
= (double)half(y2
, y3
);
1428 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1429 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1430 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1431 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1433 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1434 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1435 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1436 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1442 /* utilities used by spline drawing routines */
1445 typedef struct wx_spline_stack_struct
{
1446 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1450 #define SPLINE_STACK_DEPTH 20
1451 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1452 static Stack
*wx_stack_top
;
1453 static int wx_stack_count
;
1455 void wx_clear_stack()
1457 wx_stack_top
= wx_spline_stack
;
1461 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1463 wx_stack_top
->x1
= x1
;
1464 wx_stack_top
->y1
= y1
;
1465 wx_stack_top
->x2
= x2
;
1466 wx_stack_top
->y2
= y2
;
1467 wx_stack_top
->x3
= x3
;
1468 wx_stack_top
->y3
= y3
;
1469 wx_stack_top
->x4
= x4
;
1470 wx_stack_top
->y4
= y4
;
1475 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1476 double *x3
, double *y3
, double *x4
, double *y4
)
1478 if (wx_stack_count
== 0)
1482 *x1
= wx_stack_top
->x1
;
1483 *y1
= wx_stack_top
->y1
;
1484 *x2
= wx_stack_top
->x2
;
1485 *y2
= wx_stack_top
->y2
;
1486 *x3
= wx_stack_top
->x3
;
1487 *y3
= wx_stack_top
->y3
;
1488 *x4
= wx_stack_top
->x4
;
1489 *y4
= wx_stack_top
->y4
;
1493 static bool wx_spline_add_point(double x
, double y
)
1495 wxPoint
*point
= new wxPoint
;
1498 wx_spline_point_list
.Append((wxObject
*)point
);
1502 static void wx_spline_draw_point_array(wxDC
*dc
)
1504 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1505 wxNode
*node
= wx_spline_point_list
.First();
1508 wxPoint
*point
= (wxPoint
*)node
->Data();
1511 node
= wx_spline_point_list
.First();
1515 wxSpline::wxSpline(wxList
*list
)
1520 wxSpline::~wxSpline()
1524 void wxSpline::DeletePoints()
1526 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1528 wxPoint
*point
= (wxPoint
*)node
->Data();
1536 #endif // wxUSE_SPLINES