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
49 #if wxUSE_NORLANDER_HEADERS
59 #include "wx/msw/private.h"
61 #if !USE_SHARED_LIBRARY
62 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
65 // ---------------------------------------------------------------------------
67 // ---------------------------------------------------------------------------
69 static const int VIEWPORT_EXTENT
= 1000;
71 static const int MM_POINTS
= 9;
72 static const int MM_METRIC
= 10;
74 // ===========================================================================
76 // ===========================================================================
78 // ---------------------------------------------------------------------------
80 // ---------------------------------------------------------------------------
82 // Default constructor
96 m_windowExtX
= VIEWPORT_EXTENT
;
97 m_windowExtY
= VIEWPORT_EXTENT
;
106 SelectOldObjects(m_hDC
);
108 if ( m_canvas
== NULL
)
109 ::DeleteDC(GetHdc());
111 ::ReleaseDC((HWND
)m_canvas
->GetHWND(), GetHdc());
117 // This will select current objects out of the DC,
118 // which is what you have to do before deleting the
120 void wxDC::SelectOldObjects(WXHDC dc
)
126 ::SelectObject((HDC
) dc
, (HBITMAP
) m_oldBitmap
);
127 if (m_selectedBitmap
.Ok())
129 m_selectedBitmap
.SetSelectedInto(NULL
);
135 ::SelectObject((HDC
) dc
, (HPEN
) m_oldPen
);
140 ::SelectObject((HDC
) dc
, (HBRUSH
) m_oldBrush
);
145 ::SelectObject((HDC
) dc
, (HFONT
) m_oldFont
);
150 ::SelectPalette((HDC
) dc
, (HPALETTE
) m_oldPalette
, TRUE
);
155 m_brush
= wxNullBrush
;
157 m_palette
= wxNullPalette
;
159 m_backgroundBrush
= wxNullBrush
;
160 m_selectedBitmap
= wxNullBitmap
;
163 // ---------------------------------------------------------------------------
165 // ---------------------------------------------------------------------------
167 void wxDC::DoSetClippingRegion(long cx
, long cy
, long cw
, long ch
)
172 m_clipX2
= (int)(cx
+ cw
);
173 m_clipY2
= (int)(cy
+ ch
);
175 DoClipping((WXHDC
) m_hDC
);
178 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
180 wxCHECK_RET( region
.GetHRGN(), wxT("invalid clipping region") );
182 wxRect box
= region
.GetBox();
187 m_clipX2
= box
.x
+ box
.width
;
188 m_clipY2
= box
.y
+ box
.height
;
191 SelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN());
193 ExtSelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN(), RGN_AND
);
197 void wxDC::DoClipping(WXHDC dc
)
199 if (m_clipping
&& dc
)
201 IntersectClipRect((HDC
) dc
, XLOG2DEV(m_clipX1
), YLOG2DEV(m_clipY1
),
202 XLOG2DEV(m_clipX2
), YLOG2DEV(m_clipY2
));
206 void wxDC::DestroyClippingRegion()
208 if (m_clipping
&& m_hDC
)
210 // TODO: this should restore the previous clipping region,
211 // so that OnPaint processing works correctly, and the update clipping region
212 // doesn't get destroyed after the first DestroyClippingRegion.
213 HRGN rgn
= CreateRectRgn(0, 0, 32000, 32000);
214 SelectClipRgn(GetHdc(), rgn
);
220 // ---------------------------------------------------------------------------
221 // query capabilities
222 // ---------------------------------------------------------------------------
224 bool wxDC::CanDrawBitmap() const
229 bool wxDC::CanGetTextExtent() const
231 // What sort of display is it?
232 int technology
= ::GetDeviceCaps(GetHdc(), TECHNOLOGY
);
234 return (technology
== DT_RASDISPLAY
) || (technology
== DT_RASPRINTER
);
237 int wxDC::GetDepth() const
239 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL
);
242 // ---------------------------------------------------------------------------
244 // ---------------------------------------------------------------------------
251 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
255 wxCHECK_RET( m_selectedBitmap
.Ok(), wxT("this DC can't be cleared") );
257 rect
.left
= 0; rect
.top
= 0;
258 rect
.right
= m_selectedBitmap
.GetWidth();
259 rect
.bottom
= m_selectedBitmap
.GetHeight();
262 (void) ::SetMapMode(GetHdc(), MM_TEXT
);
264 DWORD colour
= GetBkColor(GetHdc());
265 HBRUSH brush
= CreateSolidBrush(colour
);
266 FillRect(GetHdc(), &rect
, brush
);
269 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
270 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
271 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
272 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
273 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
276 void wxDC::DoFloodFill(long x
, long y
, const wxColour
& col
, int style
)
278 (void)ExtFloodFill(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
280 style
== wxFLOOD_SURFACE
? FLOODFILLSURFACE
283 CalcBoundingBox(x
, y
);
286 bool wxDC::DoGetPixel(long x
, long y
, wxColour
*col
) const
288 // added by steve 29.12.94 (copied from DrawPoint)
289 // returns TRUE for pixels in the color of the current pen
290 // and FALSE for all other pixels colors
291 // if col is non-NULL return the color of the pixel
293 // get the color of the pixel
294 COLORREF pixelcolor
= ::GetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
));
295 // get the color of the pen
296 COLORREF pencolor
= 0x00ffffff;
299 pencolor
= m_pen
.GetColour().GetPixel();
302 // return the color of the pixel
304 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
306 // check, if color of the pixels is the same as the color
307 // of the current pen
308 return(pixelcolor
==pencolor
);
311 void wxDC::DoCrossHair(long x
, long y
)
313 long x1
= x
-VIEWPORT_EXTENT
;
314 long y1
= y
-VIEWPORT_EXTENT
;
315 long x2
= x
+VIEWPORT_EXTENT
;
316 long y2
= y
+VIEWPORT_EXTENT
;
318 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
319 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y
));
321 (void)MoveToEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
322 (void)LineTo(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y2
));
324 CalcBoundingBox(x1
, y1
);
325 CalcBoundingBox(x2
, y2
);
328 void wxDC::DoDrawLine(long x1
, long y1
, long x2
, long y2
)
330 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
331 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y2
));
333 /* MATTHEW: [6] New normalization */
334 #if WX_STANDARD_GRAPHICS
335 (void)LineTo(GetHdc(), XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
338 CalcBoundingBox(x1
, y1
);
339 CalcBoundingBox(x2
, y2
);
342 void wxDC::DoDrawArc(long x1
,long y1
,long x2
,long y2
, long xc
, long yc
)
346 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
347 if (x1
==x2
&& x2
==y2
)
349 DrawEllipse(xc
,yc
,(long)(radius
*2.0),(long)(radius
*2.0));
353 long xx1
= XLOG2DEV(x1
);
354 long yy1
= YLOG2DEV(y1
);
355 long xx2
= XLOG2DEV(x2
);
356 long yy2
= YLOG2DEV(y2
);
357 long xxc
= XLOG2DEV(xc
);
358 long yyc
= YLOG2DEV(yc
);
359 long ray
= (long) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
)));
361 (void)MoveToEx(GetHdc(), (int) xx1
, (int) yy1
, NULL
);
362 long xxx1
= (long) (xxc
-ray
);
363 long yyy1
= (long) (yyc
-ray
);
364 long xxx2
= (long) (xxc
+ray
);
365 long yyy2
= (long) (yyc
+ray
);
366 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
368 // Have to add 1 to bottom-right corner of rectangle
369 // to make semi-circles look right (crooked line otherwise).
370 // Unfortunately this is not a reliable method, depends
371 // on the size of shape.
372 // TODO: figure out why this happens!
373 Pie(GetHdc(),xxx1
,yyy1
,xxx2
+1,yyy2
+1,
377 Arc(GetHdc(),xxx1
,yyy1
,xxx2
,yyy2
,
380 CalcBoundingBox((long)(xc
-radius
), (long)(yc
-radius
));
381 CalcBoundingBox((long)(xc
+radius
), (long)(yc
+radius
));
384 void wxDC::DoDrawPoint(long x
, long y
)
386 COLORREF color
= 0x00ffffff;
389 color
= m_pen
.GetColour().GetPixel();
392 SetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), color
);
394 CalcBoundingBox(x
, y
);
397 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], long xoffset
, long yoffset
,int fillStyle
)
399 // Do things less efficiently if we have offsets
400 if (xoffset
!= 0 || yoffset
!= 0)
402 POINT
*cpoints
= new POINT
[n
];
404 for (i
= 0; i
< n
; i
++)
406 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
407 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
409 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
411 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
412 (void)Polygon(GetHdc(), cpoints
, n
);
413 SetPolyFillMode(GetHdc(),prev
);
419 for (i
= 0; i
< n
; i
++)
420 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
422 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
423 (void)Polygon(GetHdc(), (POINT
*) points
, n
);
424 SetPolyFillMode(GetHdc(),prev
);
428 void wxDC::DoDrawLines(int n
, wxPoint points
[], long xoffset
, long yoffset
)
430 // Do things less efficiently if we have offsets
431 if (xoffset
!= 0 || yoffset
!= 0)
433 POINT
*cpoints
= new POINT
[n
];
435 for (i
= 0; i
< n
; i
++)
437 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
438 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
440 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
442 (void)Polyline(GetHdc(), cpoints
, n
);
448 for (i
= 0; i
< n
; i
++)
449 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
451 (void)Polyline(GetHdc(), (POINT
*) points
, n
);
455 void wxDC::DoDrawRectangle(long x
, long y
, long width
, long height
)
458 long y2
= y
+ height
;
460 /* MATTHEW: [6] new normalization */
461 #if WX_STANDARD_GRAPHICS
462 bool do_brush
, do_pen
;
464 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
465 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
468 HPEN orig_pen
= NULL
;
470 if (do_pen
|| !m_pen
.Ok())
471 orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
473 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
474 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
476 if (do_pen
|| !m_pen
.Ok())
477 ::SelectObject(GetHdc() , orig_pen
);
480 HBRUSH orig_brush
= NULL
;
482 if (do_brush
|| !m_brush
.Ok())
483 orig_brush
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
485 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
486 XLOG2DEV(x2
), YLOG2DEV(y2
));
488 if (do_brush
|| !m_brush
.Ok())
489 ::SelectObject(GetHdc(), orig_brush
);
492 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
495 CalcBoundingBox(x
, y
);
496 CalcBoundingBox(x2
, y2
);
499 void wxDC::DoDrawRoundedRectangle(long x
, long y
, long width
, long height
, double radius
)
501 // Now, a negative radius value is interpreted to mean
502 // 'the proportion of the smallest X or Y dimension'
506 double smallest
= 0.0;
511 radius
= (- radius
* smallest
);
515 long y2
= (y
+height
);
517 (void)RoundRect(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
518 YLOG2DEV(y2
), (int) (2*XLOG2DEV(radius
)), (int)( 2*YLOG2DEV(radius
)));
520 CalcBoundingBox(x
, y
);
521 CalcBoundingBox(x2
, y2
);
524 void wxDC::DoDrawEllipse(long x
, long y
, long width
, long height
)
527 long y2
= (y
+height
);
529 (void)Ellipse(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
531 CalcBoundingBox(x
, y
);
532 CalcBoundingBox(x2
, y2
);
535 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
536 void wxDC::DoDrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
)
541 const double deg2rad
= 3.14159265359 / 180.0;
542 int rx1
= XLOG2DEV(x
+w
/2);
543 int ry1
= YLOG2DEV(y
+h
/2);
546 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
547 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
548 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
549 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
551 // draw pie with NULL_PEN first and then outline otherwise a line is
552 // drawn from the start and end points to the centre
553 HPEN orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
556 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
561 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
562 rx1
, ry1
-1, rx2
, ry2
-1);
564 ::SelectObject(GetHdc(), orig_pen
);
565 (void)Arc(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
568 CalcBoundingBox(x
, y
);
569 CalcBoundingBox(x2
, y2
);
572 void wxDC::DoDrawIcon(const wxIcon
& icon
, long x
, long y
)
574 #if defined(__WIN32__) && !defined(__SC__) && !defined(__TWIN32__)
575 ::DrawIconEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON(),
576 icon
.GetWidth(), icon
.GetHeight(), 0, 0, DI_NORMAL
);
578 ::DrawIcon(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
581 CalcBoundingBox(x
, y
);
582 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
585 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, long x
, long y
, bool useMask
)
590 // If we're not drawing transparently, and not drawing to a printer,
591 // optimize this function to use Windows functions.
592 if (!useMask
&& !IsKindOf(CLASSINFO(wxPrinterDC
)))
595 HDC memdc
= ::CreateCompatibleDC( cdc
);
596 HBITMAP hbitmap
= (HBITMAP
) bmp
.GetHBITMAP( );
598 wxASSERT_MSG( hbitmap
, wxT("bitmap is ok but HBITMAP is NULL?") );
600 ::SelectObject( memdc
, hbitmap
);
601 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
606 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
608 memDC
.SelectObject(bmp
);
610 /* Not sure if we need this. The mask should leave the
611 * masked areas as per the original background of this DC.
614 // There might be transparent areas, so make these
615 // the same colour as this DC
616 memDC.SetBackground(* GetBackground());
620 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
622 memDC
.SelectObject(wxNullBitmap
);
626 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
628 if (m_textForegroundColour
.Ok())
629 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
631 DWORD old_background
= 0;
632 if (m_textBackgroundColour
.Ok())
634 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
637 if (m_backgroundMode
== wxTRANSPARENT
)
638 SetBkMode(GetHdc(), TRANSPARENT
);
640 SetBkMode(GetHdc(), OPAQUE
);
642 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), WXSTRINGCAST text
, wxStrlen(WXSTRINGCAST text
));
644 if (m_textBackgroundColour
.Ok())
645 (void)SetBkColor(GetHdc(), old_background
);
647 // background colour is used only for DrawText, otherwise
648 // always TRANSPARENT, RR
649 SetBkMode(GetHdc(), TRANSPARENT
);
651 CalcBoundingBox(x
, y
);
654 GetTextExtent(text
, &w
, &h
);
655 CalcBoundingBox((x
+ w
), (y
+ h
));
658 // ---------------------------------------------------------------------------
660 // ---------------------------------------------------------------------------
662 void wxDC::SetPalette(const wxPalette
& palette
)
664 // Set the old object temporarily, in case the assignment deletes an object
665 // that's not yet selected out.
668 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
676 // Setting a NULL colourmap is a way of restoring
677 // the original colourmap
680 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
687 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
689 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
691 m_oldPalette
= (WXHPALETTE
) oldPal
;
693 ::RealizePalette(GetHdc());
697 void wxDC::SetFont(const wxFont
& the_font
)
699 // Set the old object temporarily, in case the assignment deletes an object
700 // that's not yet selected out.
703 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
712 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
716 if (m_font
.Ok() && m_font
.GetResourceHandle())
718 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
719 if (f
== (HFONT
) NULL
)
721 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
724 m_oldFont
= (WXHFONT
) f
;
728 void wxDC::SetPen(const wxPen
& pen
)
730 // Set the old object temporarily, in case the assignment deletes an object
731 // that's not yet selected out.
734 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
743 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
749 if (m_pen
.GetResourceHandle())
751 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
753 m_oldPen
= (WXHPEN
) p
;
758 void wxDC::SetBrush(const wxBrush
& brush
)
760 // Set the old object temporarily, in case the assignment deletes an object
761 // that's not yet selected out.
764 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
773 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
779 if (m_brush
.GetResourceHandle())
782 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
784 m_oldBrush
= (WXHBRUSH
) b
;
789 void wxDC::SetBackground(const wxBrush
& brush
)
791 m_backgroundBrush
= brush
;
793 if (!m_backgroundBrush
.Ok())
798 bool customColours
= TRUE
;
799 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
800 // change background colours from the control-panel specified colours.
801 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
802 customColours
= FALSE
;
806 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
808 m_canvas
->SetTransparent(TRUE
);
812 // New behaviour, 10/2/99: setting the background brush of a DC
813 // doesn't affect the window background colour. However,
814 // I'm leaving in the transparency setting because it's needed by
815 // various controls (e.g. wxStaticText) to determine whether to draw
816 // transparently or not. TODO: maybe this should be a new function
817 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
819 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
820 m_canvas
->SetTransparent(FALSE
);
824 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
826 (void)SetBkColor(GetHdc(), new_color
);
830 void wxDC::SetBackgroundMode(int mode
)
832 m_backgroundMode
= mode
;
834 // SetBackgroundColour now only refers to text background
835 // and m_backgroundMode is used there
838 if (m_backgroundMode == wxTRANSPARENT)
839 ::SetBkMode(GetHdc(), TRANSPARENT);
841 ::SetBkMode(GetHdc(), OPAQUE);
845 void wxDC::SetLogicalFunction(int function
)
847 m_logicalFunction
= function
;
849 SetRop((WXHDC
) m_hDC
);
852 void wxDC::SetRop(WXHDC dc
)
854 if (!dc
|| m_logicalFunction
< 0)
858 // These may be wrong
859 switch (m_logicalFunction
)
861 // case wxXOR: c_rop = R2_XORPEN; break;
862 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
863 case wxINVERT
: c_rop
= R2_NOT
; break;
864 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
865 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
866 case wxCLEAR
: c_rop
= R2_WHITE
; break;
867 case wxSET
: c_rop
= R2_BLACK
; break;
868 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
869 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
870 case wxAND
: c_rop
= R2_MASKPEN
; break;
871 case wxOR
: c_rop
= R2_MERGEPEN
; break;
872 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
877 c_rop
= R2_COPYPEN
; break;
879 SetROP2((HDC
) dc
, c_rop
);
882 bool wxDC::StartDoc(const wxString
& message
)
884 // We might be previewing, so return TRUE to let it continue.
892 void wxDC::StartPage()
900 // ---------------------------------------------------------------------------
902 // ---------------------------------------------------------------------------
904 long wxDC::GetCharHeight() const
906 TEXTMETRIC lpTextMetric
;
908 GetTextMetrics(GetHdc(), &lpTextMetric
);
910 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
913 long wxDC::GetCharWidth() const
915 TEXTMETRIC lpTextMetric
;
917 GetTextMetrics(GetHdc(), &lpTextMetric
);
919 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
922 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
923 long *descent
, long *externalLeading
,
924 wxFont
*theFont
) const
926 wxFont
*fontToUse
= (wxFont
*) theFont
;
928 fontToUse
= (wxFont
*) &m_font
;
933 GetTextExtentPoint(GetHdc(), WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
934 GetTextMetrics(GetHdc(), &tm
);
936 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
937 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
938 if (descent
) *descent
= tm
.tmDescent
;
939 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
942 void wxDC::SetMapMode(int mode
)
944 m_mappingMode
= mode
;
947 int pixel_height
= 0;
951 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
952 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
953 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
954 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
956 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
961 double mm2pixelsX
= pixel_width
/mm_width
;
962 double mm2pixelsY
= pixel_height
/mm_height
;
968 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
969 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
974 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
975 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
980 m_logicalScaleX
= mm2pixelsX
;
981 m_logicalScaleY
= mm2pixelsY
;
986 m_logicalScaleX
= (mm2pixelsX
/10.0);
987 m_logicalScaleY
= (mm2pixelsY
/10.0);
993 m_logicalScaleX
= 1.0;
994 m_logicalScaleY
= 1.0;
999 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
1000 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
1002 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1003 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1004 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1005 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1006 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1007 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1010 void wxDC::SetUserScale(double x
, double y
)
1015 SetMapMode(m_mappingMode
);
1018 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1020 m_signX
= xLeftRight
? 1 : -1;
1021 m_signY
= yBottomUp
? -1 : 1;
1023 SetMapMode(m_mappingMode
);
1026 void wxDC::SetSystemScale(double x
, double y
)
1031 SetMapMode(m_mappingMode
);
1034 void wxDC::SetLogicalOrigin(long x
, long y
)
1036 m_logicalOriginX
= x
;
1037 m_logicalOriginY
= y
;
1039 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1042 void wxDC::SetDeviceOrigin(long x
, long y
)
1044 m_deviceOriginX
= x
;
1045 m_deviceOriginY
= y
;
1047 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1050 // ---------------------------------------------------------------------------
1051 // coordinates transformations
1052 // ---------------------------------------------------------------------------
1054 long wxDCBase::DeviceToLogicalX(long x
) const
1056 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1059 long wxDCBase::DeviceToLogicalXRel(long x
) const
1061 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1064 long wxDCBase::DeviceToLogicalY(long y
) const
1066 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1069 long wxDCBase::DeviceToLogicalYRel(long y
) const
1071 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1074 long wxDCBase::LogicalToDeviceX(long x
) const
1076 return (long) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1079 long wxDCBase::LogicalToDeviceXRel(long x
) const
1081 return (long) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1084 long wxDCBase::LogicalToDeviceY(long y
) const
1086 return (long) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1089 long wxDCBase::LogicalToDeviceYRel(long y
) const
1091 return (long) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1094 // ---------------------------------------------------------------------------
1096 // ---------------------------------------------------------------------------
1097 bool wxDC::DoBlit(long xdest
, long ydest
, long width
, long height
,
1098 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1100 long xdest1
= xdest
;
1101 long ydest1
= ydest
;
1105 // Chris Breeze 18/5/98: use text foreground/background colours
1106 // when blitting from 1-bit bitmaps
1107 COLORREF old_textground
= ::GetTextColor(GetHdc());
1108 COLORREF old_background
= ::GetBkColor(GetHdc());
1109 if (m_textForegroundColour
.Ok())
1111 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1113 if (m_textBackgroundColour
.Ok())
1115 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1118 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1119 rop
== wxCLEAR
? WHITENESS
:
1120 rop
== wxSET
? BLACKNESS
:
1121 rop
== wxINVERT
? DSTINVERT
:
1122 rop
== wxAND
? MERGECOPY
:
1123 rop
== wxOR
? MERGEPAINT
:
1124 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1125 rop
== wxXOR
? SRCINVERT
:
1126 rop
== wxOR_REVERSE
? MERGEPAINT
:
1127 rop
== wxAND_REVERSE
? SRCERASE
:
1128 rop
== wxSRC_OR
? SRCPAINT
:
1129 rop
== wxSRC_AND
? SRCAND
:
1132 bool success
= TRUE
;
1133 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1137 // Not implemented under Win95 (or maybe a specific device?)
1138 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1139 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1149 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1150 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1151 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1152 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1153 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1154 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1155 ::SelectObject(dc_mask
, 0);
1156 ::DeleteDC(dc_mask
);
1158 // New code from Chris Breeze, 15/7/98
1159 // Blit bitmap with mask
1161 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1163 // If we are printing source colours are screen colours
1164 // not printer colours and so we need copy the bitmap
1167 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1168 HDC dc_src
= (HDC
) source
->m_hDC
;
1170 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1171 for (int x
= 0; x
< width
; x
++)
1173 for (int y
= 0; y
< height
; y
++)
1175 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1178 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1179 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1180 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1181 ::FillRect(GetHdc(), &rect
, brush
);
1182 ::DeleteObject(brush
);
1186 ::SelectObject(dc_mask
, 0);
1187 ::DeleteDC(dc_mask
);
1191 // create a temp buffer bitmap and DCs to access it and the mask
1192 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1193 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1194 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1195 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1196 ::SelectObject(dc_buffer
, buffer_bmap
);
1198 // copy dest to buffer
1199 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1200 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1202 // copy src to buffer using selected raster op
1203 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1204 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1206 // set masked area in buffer to BLACK (pixel value 0)
1207 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1208 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1209 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1210 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1212 // set unmasked area in dest to BLACK
1213 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1214 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1215 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1216 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1217 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1218 ::SetTextColor(GetHdc(), prevCol
);
1220 // OR buffer to dest
1221 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1222 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1224 // tidy up temporary DCs and bitmap
1225 ::SelectObject(dc_mask
, 0);
1226 ::DeleteDC(dc_mask
);
1227 ::SelectObject(dc_buffer
, 0);
1228 ::DeleteDC(dc_buffer
);
1229 ::DeleteObject(buffer_bmap
);
1235 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1237 // If we are printing, source colours are screen colours
1238 // not printer colours and so we need copy the bitmap
1240 HDC dc_src
= (HDC
) source
->m_hDC
;
1242 for (int x
= 0; x
< width
; x
++)
1244 for (int y
= 0; y
< height
; y
++)
1246 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1247 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1248 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1249 ::FillRect(GetHdc(), &rect
, brush
);
1250 ::DeleteObject(brush
);
1256 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1257 xsrc1
, ysrc1
, dwRop
) != 0);
1260 ::SetTextColor(GetHdc(), old_textground
);
1261 ::SetBkColor(GetHdc(), old_background
);
1266 void wxDC::DoGetSize(int *w
, int *h
) const
1268 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1269 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1272 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1274 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1275 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1278 wxSize
wxDC::GetPPI() const
1280 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1281 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1283 return wxSize(x
, y
);
1286 // For use by wxWindows only, unless custom units are required.
1287 void wxDC::SetLogicalScale(double x
, double y
)
1289 m_logicalScaleX
= x
;
1290 m_logicalScaleY
= y
;
1293 #if WXWIN_COMPATIBILITY
1294 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1295 float *descent
, float *externalLeading
,
1296 wxFont
*theFont
, bool use16bit
) const
1298 long x1
, y1
, descent1
, externalLeading1
;
1299 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1302 *descent
= descent1
;
1303 if (externalLeading
)
1304 *externalLeading
= externalLeading1
;
1308 // ---------------------------------------------------------------------------
1309 // spline drawing code
1310 // ---------------------------------------------------------------------------
1314 class wxSpline
: public wxObject
1320 wxSpline(wxList
*list
);
1321 void DeletePoints();
1323 // Doesn't delete points
1327 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1329 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1330 double a3
, double b3
, double a4
, double b4
);
1331 void wx_clear_stack();
1332 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1333 double *y3
, double *x4
, double *y4
);
1334 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1335 double x4
, double y4
);
1336 static bool wx_spline_add_point(double x
, double y
);
1337 static void wx_spline_draw_point_array(wxDC
*dc
);
1338 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1340 void wxDC::DoDrawSpline(wxList
*list
)
1342 wxSpline
spline(list
);
1344 wx_draw_open_spline(this, &spline
);
1347 wxList wx_spline_point_list
;
1349 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1352 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1353 double x1
, y1
, x2
, y2
;
1355 wxNode
*node
= spline
->points
->First();
1356 p
= (wxPoint
*)node
->Data();
1361 node
= node
->Next();
1362 p
= (wxPoint
*)node
->Data();
1366 cx1
= (double)((x1
+ x2
) / 2);
1367 cy1
= (double)((y1
+ y2
) / 2);
1368 cx2
= (double)((cx1
+ x2
) / 2);
1369 cy2
= (double)((cy1
+ y2
) / 2);
1371 wx_spline_add_point(x1
, y1
);
1373 while ((node
= node
->Next()) != NULL
)
1375 p
= (wxPoint
*)node
->Data();
1380 cx4
= (double)(x1
+ x2
) / 2;
1381 cy4
= (double)(y1
+ y2
) / 2;
1382 cx3
= (double)(x1
+ cx4
) / 2;
1383 cy3
= (double)(y1
+ cy4
) / 2;
1385 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1389 cx2
= (double)(cx1
+ x2
) / 2;
1390 cy2
= (double)(cy1
+ y2
) / 2;
1393 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1394 wx_spline_add_point(x2
, y2
);
1396 wx_spline_draw_point_array(dc
);
1400 /********************* CURVES FOR SPLINES *****************************
1402 The following spline drawing routine is from
1404 "An Algorithm for High-Speed Curve Generation"
1405 by George Merrill Chaikin,
1406 Computer Graphics and Image Processing, 3, Academic Press,
1411 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1412 Computer Graphics and Image Processing, 4, Academic Press,
1415 ***********************************************************************/
1417 #define half(z1, z2) ((z1+z2)/2.0)
1420 /* iterative version */
1422 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1425 register double xmid
, ymid
;
1426 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1429 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1431 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1432 xmid
= (double)half(x2
, x3
);
1433 ymid
= (double)half(y2
, y3
);
1434 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1435 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1436 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1437 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1439 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1440 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1441 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1442 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1448 /* utilities used by spline drawing routines */
1451 typedef struct wx_spline_stack_struct
{
1452 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1456 #define SPLINE_STACK_DEPTH 20
1457 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1458 static Stack
*wx_stack_top
;
1459 static int wx_stack_count
;
1461 void wx_clear_stack()
1463 wx_stack_top
= wx_spline_stack
;
1467 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1469 wx_stack_top
->x1
= x1
;
1470 wx_stack_top
->y1
= y1
;
1471 wx_stack_top
->x2
= x2
;
1472 wx_stack_top
->y2
= y2
;
1473 wx_stack_top
->x3
= x3
;
1474 wx_stack_top
->y3
= y3
;
1475 wx_stack_top
->x4
= x4
;
1476 wx_stack_top
->y4
= y4
;
1481 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1482 double *x3
, double *y3
, double *x4
, double *y4
)
1484 if (wx_stack_count
== 0)
1488 *x1
= wx_stack_top
->x1
;
1489 *y1
= wx_stack_top
->y1
;
1490 *x2
= wx_stack_top
->x2
;
1491 *y2
= wx_stack_top
->y2
;
1492 *x3
= wx_stack_top
->x3
;
1493 *y3
= wx_stack_top
->y3
;
1494 *x4
= wx_stack_top
->x4
;
1495 *y4
= wx_stack_top
->y4
;
1499 static bool wx_spline_add_point(double x
, double y
)
1501 wxPoint
*point
= new wxPoint
;
1504 wx_spline_point_list
.Append((wxObject
*)point
);
1508 static void wx_spline_draw_point_array(wxDC
*dc
)
1510 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1511 wxNode
*node
= wx_spline_point_list
.First();
1514 wxPoint
*point
= (wxPoint
*)node
->Data();
1517 node
= wx_spline_point_list
.First();
1521 wxSpline::wxSpline(wxList
*list
)
1526 wxSpline::~wxSpline()
1530 void wxSpline::DeletePoints()
1532 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1534 wxPoint
*point
= (wxPoint
*)node
->Data();
1542 #endif // wxUSE_SPLINES