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 // ---------------------------------------------------------------------------
77 #define XLOG2DEV(x) (x)
78 #define YLOG2DEV(y) (y)
81 #define XLOG2DEVREL(x) (x)
82 #define YLOG2DEVREL(y) (y)
86 #define XDEV2LOG(x) (x)
88 #define YDEV2LOG(y) (y)
91 #define XDEV2LOGREL(x) (x)
92 #define YDEV2LOGREL(y) (y)
95 * Have the same macros as for XView but not for every operation:
96 * just for calculating window/viewport extent (a better way of scaling).
101 #define MS_XLOG2DEV(x) LogicalToDevice(x)
103 #define MS_YLOG2DEV(y) LogicalToDevice(y)
106 #define MS_XLOG2DEVREL(x) LogicalToDeviceXRel(x)
107 #define MS_YLOG2DEVREL(y) LogicalToDeviceYRel(y)
111 #define MS_XDEV2LOG(x) DeviceToLogicalX(x)
113 #define MS_YDEV2LOG(y) DeviceToLogicalY(y)
116 #define MS_XDEV2LOGREL(x) DeviceToLogicalXRel(x)
117 #define MS_YDEV2LOGREL(y) DeviceToLogicalYRel(y)
119 #define YSCALE(y) (yorigin - (y))
121 #define wx_round(a) (int)((a)+.5)
123 // ===========================================================================
125 // ===========================================================================
127 // ---------------------------------------------------------------------------
129 // ---------------------------------------------------------------------------
131 // Default constructor
145 m_windowExtX
= VIEWPORT_EXTENT
;
146 m_windowExtY
= VIEWPORT_EXTENT
;
155 SelectOldObjects(m_hDC
);
157 if ( m_canvas
== NULL
)
158 ::DeleteDC(GetHdc());
160 ::ReleaseDC((HWND
)m_canvas
->GetHWND(), GetHdc());
166 // This will select current objects out of the DC,
167 // which is what you have to do before deleting the
169 void wxDC::SelectOldObjects(WXHDC dc
)
175 ::SelectObject((HDC
) dc
, (HBITMAP
) m_oldBitmap
);
176 if (m_selectedBitmap
.Ok())
178 m_selectedBitmap
.SetSelectedInto(NULL
);
184 ::SelectObject((HDC
) dc
, (HPEN
) m_oldPen
);
189 ::SelectObject((HDC
) dc
, (HBRUSH
) m_oldBrush
);
194 ::SelectObject((HDC
) dc
, (HFONT
) m_oldFont
);
199 ::SelectPalette((HDC
) dc
, (HPALETTE
) m_oldPalette
, TRUE
);
204 m_brush
= wxNullBrush
;
206 m_palette
= wxNullPalette
;
208 m_backgroundBrush
= wxNullBrush
;
209 m_selectedBitmap
= wxNullBitmap
;
212 // ---------------------------------------------------------------------------
214 // ---------------------------------------------------------------------------
216 void wxDC::DoSetClippingRegion(long cx
, long cy
, long cw
, long ch
)
221 m_clipX2
= (int)(cx
+ cw
);
222 m_clipY2
= (int)(cy
+ ch
);
224 DoClipping((WXHDC
) m_hDC
);
227 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
229 wxCHECK_RET( region
.GetHRGN(), _T("invalid clipping region") );
231 wxRect box
= region
.GetBox();
236 m_clipX2
= box
.x
+ box
.width
;
237 m_clipY2
= box
.y
+ box
.height
;
240 SelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN());
242 ExtSelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN(), RGN_AND
);
246 void wxDC::DoClipping(WXHDC dc
)
248 if (m_clipping
&& dc
)
250 IntersectClipRect((HDC
) dc
, XLOG2DEV(m_clipX1
), YLOG2DEV(m_clipY1
),
251 XLOG2DEV(m_clipX2
), YLOG2DEV(m_clipY2
));
255 void wxDC::DestroyClippingRegion()
257 if (m_clipping
&& m_hDC
)
259 // TODO: this should restore the previous clipping region,
260 // so that OnPaint processing works correctly, and the update clipping region
261 // doesn't get destroyed after the first DestroyClippingRegion.
262 HRGN rgn
= CreateRectRgn(0, 0, 32000, 32000);
263 SelectClipRgn(GetHdc(), rgn
);
269 // ---------------------------------------------------------------------------
270 // query capabilities
271 // ---------------------------------------------------------------------------
273 bool wxDC::CanDrawBitmap() const
278 bool wxDC::CanGetTextExtent() const
280 // What sort of display is it?
281 int technology
= ::GetDeviceCaps(GetHdc(), TECHNOLOGY
);
283 return (technology
== DT_RASDISPLAY
) || (technology
== DT_RASPRINTER
);
286 int wxDC::GetDepth() const
288 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL
);
291 // ---------------------------------------------------------------------------
293 // ---------------------------------------------------------------------------
299 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
300 else if (m_selectedBitmap
.Ok())
302 rect
.left
= 0; rect
.top
= 0;
303 rect
.right
= m_selectedBitmap
.GetWidth();
304 rect
.bottom
= m_selectedBitmap
.GetHeight();
306 (void) ::SetMapMode(GetHdc(), MM_TEXT
);
308 DWORD colour
= GetBkColor(GetHdc());
309 HBRUSH brush
= CreateSolidBrush(colour
);
310 FillRect(GetHdc(), &rect
, brush
);
313 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
314 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
315 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
316 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
317 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
320 void wxDC::DoFloodFill(long x
, long y
, const wxColour
& col
, int style
)
322 (void)ExtFloodFill(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
324 style
== wxFLOOD_SURFACE
? FLOODFILLSURFACE
327 CalcBoundingBox(x
, y
);
330 bool wxDC::DoGetPixel(long x
, long y
, wxColour
*col
) const
332 // added by steve 29.12.94 (copied from DrawPoint)
333 // returns TRUE for pixels in the color of the current pen
334 // and FALSE for all other pixels colors
335 // if col is non-NULL return the color of the pixel
337 // get the color of the pixel
338 COLORREF pixelcolor
= ::GetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
));
339 // get the color of the pen
340 COLORREF pencolor
= 0x00ffffff;
343 pencolor
= m_pen
.GetColour().GetPixel();
346 // return the color of the pixel
348 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
350 // check, if color of the pixels is the same as the color
351 // of the current pen
352 return(pixelcolor
==pencolor
);
355 void wxDC::DoCrossHair(long x
, long y
)
357 long x1
= x
-VIEWPORT_EXTENT
;
358 long y1
= y
-VIEWPORT_EXTENT
;
359 long x2
= x
+VIEWPORT_EXTENT
;
360 long y2
= y
+VIEWPORT_EXTENT
;
362 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
363 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y
));
365 (void)MoveToEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
366 (void)LineTo(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y2
));
368 CalcBoundingBox(x1
, y1
);
369 CalcBoundingBox(x2
, y2
);
372 void wxDC::DoDrawLine(long x1
, long y1
, long x2
, long y2
)
374 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
375 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y2
));
377 /* MATTHEW: [6] New normalization */
378 #if WX_STANDARD_GRAPHICS
379 (void)LineTo(GetHdc(), XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
382 CalcBoundingBox(x1
, y1
);
383 CalcBoundingBox(x2
, y2
);
386 void wxDC::DoDrawArc(long x1
,long y1
,long x2
,long y2
, long xc
, long yc
)
390 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
391 if (x1
==x2
&& x2
==y2
)
393 DrawEllipse(xc
,yc
,(long)(radius
*2.0),(long)(radius
*2.0));
397 long xx1
= XLOG2DEV(x1
);
398 long yy1
= YLOG2DEV(y1
);
399 long xx2
= XLOG2DEV(x2
);
400 long yy2
= YLOG2DEV(y2
);
401 long xxc
= XLOG2DEV(xc
);
402 long yyc
= YLOG2DEV(yc
);
403 long ray
= (long) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
)));
405 (void)MoveToEx(GetHdc(), (int) xx1
, (int) yy1
, NULL
);
406 long xxx1
= (long) (xxc
-ray
);
407 long yyy1
= (long) (yyc
-ray
);
408 long xxx2
= (long) (xxc
+ray
);
409 long yyy2
= (long) (yyc
+ray
);
410 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
412 // Have to add 1 to bottom-right corner of rectangle
413 // to make semi-circles look right (crooked line otherwise).
414 // Unfortunately this is not a reliable method, depends
415 // on the size of shape.
416 // TODO: figure out why this happens!
417 Pie(GetHdc(),xxx1
,yyy1
,xxx2
+1,yyy2
+1,
421 Arc(GetHdc(),xxx1
,yyy1
,xxx2
,yyy2
,
424 CalcBoundingBox((xc
-radius
), (yc
-radius
));
425 CalcBoundingBox((xc
+radius
), (yc
+radius
));
428 void wxDC::DoDrawPoint(long x
, long y
)
430 COLORREF color
= 0x00ffffff;
433 color
= m_pen
.GetColour().GetPixel();
436 SetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), color
);
438 CalcBoundingBox(x
, y
);
441 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], long xoffset
, long yoffset
,int fillStyle
)
443 // Do things less efficiently if we have offsets
444 if (xoffset
!= 0 || yoffset
!= 0)
446 POINT
*cpoints
= new POINT
[n
];
448 for (i
= 0; i
< n
; i
++)
450 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
451 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
453 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
455 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
456 (void)Polygon(GetHdc(), cpoints
, n
);
457 SetPolyFillMode(GetHdc(),prev
);
463 for (i
= 0; i
< n
; i
++)
464 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
466 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
467 (void)Polygon(GetHdc(), (POINT
*) points
, n
);
468 SetPolyFillMode(GetHdc(),prev
);
472 void wxDC::DoDrawLines(int n
, wxPoint points
[], long xoffset
, long yoffset
)
474 // Do things less efficiently if we have offsets
475 if (xoffset
!= 0 || yoffset
!= 0)
477 POINT
*cpoints
= new POINT
[n
];
479 for (i
= 0; i
< n
; i
++)
481 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
482 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
484 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
486 (void)Polyline(GetHdc(), cpoints
, n
);
492 for (i
= 0; i
< n
; i
++)
493 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
495 (void)Polyline(GetHdc(), (POINT
*) points
, n
);
499 void wxDC::DoDrawRectangle(long x
, long y
, long width
, long height
)
502 long y2
= y
+ height
;
504 /* MATTHEW: [6] new normalization */
505 #if WX_STANDARD_GRAPHICS
506 bool do_brush
, do_pen
;
508 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
509 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
512 HPEN orig_pen
= NULL
;
514 if (do_pen
|| !m_pen
.Ok())
515 orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
517 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
518 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
520 if (do_pen
|| !m_pen
.Ok())
521 ::SelectObject(GetHdc() , orig_pen
);
524 HBRUSH orig_brush
= NULL
;
526 if (do_brush
|| !m_brush
.Ok())
527 orig_brush
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
529 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
530 XLOG2DEV(x2
), YLOG2DEV(y2
));
532 if (do_brush
|| !m_brush
.Ok())
533 ::SelectObject(GetHdc(), orig_brush
);
536 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
539 CalcBoundingBox(x
, y
);
540 CalcBoundingBox(x2
, y2
);
543 void wxDC::DoDrawRoundedRectangle(long x
, long y
, long width
, long height
, double radius
)
545 // Now, a negative radius value is interpreted to mean
546 // 'the proportion of the smallest X or Y dimension'
550 double smallest
= 0.0;
555 radius
= (- radius
* smallest
);
559 long y2
= (y
+height
);
561 (void)RoundRect(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
562 YLOG2DEV(y2
), 2*XLOG2DEV(radius
), 2*YLOG2DEV(radius
));
564 CalcBoundingBox(x
, y
);
565 CalcBoundingBox(x2
, y2
);
568 void wxDC::DoDrawEllipse(long x
, long y
, long width
, long height
)
571 long y2
= (y
+height
);
573 (void)Ellipse(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
575 CalcBoundingBox(x
, y
);
576 CalcBoundingBox(x2
, y2
);
579 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
580 void wxDC::DoDrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
)
585 const double deg2rad
= 3.14159265359 / 180.0;
586 int rx1
= XLOG2DEV(x
+w
/2);
587 int ry1
= YLOG2DEV(y
+h
/2);
590 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
591 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
592 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
593 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
595 // draw pie with NULL_PEN first and then outline otherwise a line is
596 // drawn from the start and end points to the centre
597 HPEN orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
600 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
605 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
606 rx1
, ry1
-1, rx2
, ry2
-1);
608 ::SelectObject(GetHdc(), orig_pen
);
609 (void)Arc(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
612 CalcBoundingBox(x
, y
);
613 CalcBoundingBox(x2
, y2
);
616 void wxDC::DoDrawIcon(const wxIcon
& icon
, long x
, long y
)
618 #if defined(__WIN32__) && !defined(__SC__) && !defined(__TWIN32__)
619 ::DrawIconEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON(),
620 icon
.GetWidth(), icon
.GetHeight(), 0, 0, DI_NORMAL
);
622 ::DrawIcon(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
625 CalcBoundingBox(x
, y
);
626 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
629 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, long x
, long y
, bool useMask
)
634 // If we're not drawing transparently, and not drawing to a printer,
635 // optimize this function to use Windows functions.
636 if (!useMask
&& !IsKindOf(CLASSINFO(wxPrinterDC
)))
639 HDC memdc
= ::CreateCompatibleDC( cdc
);
640 HBITMAP hbitmap
= (HBITMAP
) bmp
.GetHBITMAP( );
641 ::SelectObject( memdc
, hbitmap
);
642 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
647 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
649 memDC
.SelectObject(bmp
);
651 /* Not sure if we need this. The mask should leave the
652 * masked areas as per the original background of this DC.
655 // There might be transparent areas, so make these
656 // the same colour as this DC
657 memDC.SetBackground(* GetBackground());
661 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
663 memDC
.SelectObject(wxNullBitmap
);
667 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
669 if (m_textForegroundColour
.Ok())
670 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
672 DWORD old_background
= 0;
673 if (m_textBackgroundColour
.Ok())
675 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
678 if (m_backgroundMode
== wxTRANSPARENT
)
679 SetBkMode(GetHdc(), TRANSPARENT
);
681 SetBkMode(GetHdc(), OPAQUE
);
683 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (char *) (const char *)text
, strlen((const char *)text
));
685 if (m_textBackgroundColour
.Ok())
686 (void)SetBkColor(GetHdc(), old_background
);
688 CalcBoundingBox(x
, y
);
691 GetTextExtent(text
, &w
, &h
);
692 CalcBoundingBox((x
+ w
), (y
+ h
));
695 // ---------------------------------------------------------------------------
697 // ---------------------------------------------------------------------------
699 void wxDC::SetPalette(const wxPalette
& palette
)
701 // Set the old object temporarily, in case the assignment deletes an object
702 // that's not yet selected out.
705 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
713 // Setting a NULL colourmap is a way of restoring
714 // the original colourmap
717 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
724 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
726 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
728 m_oldPalette
= (WXHPALETTE
) oldPal
;
730 ::RealizePalette(GetHdc());
734 void wxDC::SetFont(const wxFont
& the_font
)
736 // Set the old object temporarily, in case the assignment deletes an object
737 // that's not yet selected out.
740 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
749 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
753 if (m_font
.Ok() && m_font
.GetResourceHandle())
755 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
756 if (f
== (HFONT
) NULL
)
758 wxLogDebug("::SelectObject failed in wxDC::SetFont.");
761 m_oldFont
= (WXHFONT
) f
;
765 void wxDC::SetPen(const wxPen
& pen
)
767 // Set the old object temporarily, in case the assignment deletes an object
768 // that's not yet selected out.
771 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
780 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
786 if (m_pen
.GetResourceHandle())
788 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
790 m_oldPen
= (WXHPEN
) p
;
795 void wxDC::SetBrush(const wxBrush
& brush
)
797 // Set the old object temporarily, in case the assignment deletes an object
798 // that's not yet selected out.
801 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
810 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
816 if (m_brush
.GetResourceHandle())
819 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
821 m_oldBrush
= (WXHBRUSH
) b
;
826 void wxDC::SetBackground(const wxBrush
& brush
)
828 m_backgroundBrush
= brush
;
830 if (!m_backgroundBrush
.Ok())
835 bool customColours
= TRUE
;
836 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
837 // change background colours from the control-panel specified colours.
838 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
839 customColours
= FALSE
;
843 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
845 m_canvas
->SetTransparent(TRUE
);
849 // New behaviour, 10/2/99: setting the background brush of a DC
850 // doesn't affect the window background colour. However,
851 // I'm leaving in the transparency setting because it's needed by
852 // various controls (e.g. wxStaticText) to determine whether to draw
853 // transparently or not. TODO: maybe this should be a new function
854 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
856 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
857 m_canvas
->SetTransparent(FALSE
);
861 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
863 (void)SetBkColor(GetHdc(), new_color
);
867 void wxDC::SetBackgroundMode(int mode
)
869 m_backgroundMode
= mode
;
871 if (m_backgroundMode
== wxTRANSPARENT
)
872 ::SetBkMode(GetHdc(), TRANSPARENT
);
874 ::SetBkMode(GetHdc(), OPAQUE
);
877 void wxDC::SetLogicalFunction(int function
)
879 m_logicalFunction
= function
;
881 SetRop((WXHDC
) m_hDC
);
884 void wxDC::SetRop(WXHDC dc
)
886 if (!dc
|| m_logicalFunction
< 0)
890 // These may be wrong
891 switch (m_logicalFunction
)
893 // case wxXOR: c_rop = R2_XORPEN; break;
894 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
895 case wxINVERT
: c_rop
= R2_NOT
; break;
896 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
897 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
898 case wxCLEAR
: c_rop
= R2_WHITE
; break;
899 case wxSET
: c_rop
= R2_BLACK
; break;
900 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
901 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
902 case wxAND
: c_rop
= R2_MASKPEN
; break;
903 case wxOR
: c_rop
= R2_MERGEPEN
; break;
904 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
909 c_rop
= R2_COPYPEN
; break;
911 SetROP2((HDC
) dc
, c_rop
);
914 bool wxDC::StartDoc(const wxString
& message
)
916 // We might be previewing, so return TRUE to let it continue.
924 void wxDC::StartPage()
932 // ---------------------------------------------------------------------------
934 // ---------------------------------------------------------------------------
936 long wxDC::GetCharHeight() const
938 TEXTMETRIC lpTextMetric
;
940 GetTextMetrics(GetHdc(), &lpTextMetric
);
942 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
945 long wxDC::GetCharWidth() const
947 TEXTMETRIC lpTextMetric
;
949 GetTextMetrics(GetHdc(), &lpTextMetric
);
951 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
954 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
955 long *descent
, long *externalLeading
,
956 wxFont
*theFont
) const
958 wxFont
*fontToUse
= (wxFont
*) theFont
;
960 fontToUse
= (wxFont
*) &m_font
;
965 GetTextExtentPoint(GetHdc(), (char *)(const char *) string
, strlen((char *)(const char *) string
), &sizeRect
);
966 GetTextMetrics(GetHdc(), &tm
);
968 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
969 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
970 if (descent
) *descent
= tm
.tmDescent
;
971 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
974 void wxDC::SetMapMode(int mode
)
976 m_mappingMode
= mode
;
979 int pixel_height
= 0;
983 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
984 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
985 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
986 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
988 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
993 double mm2pixelsX
= pixel_width
/mm_width
;
994 double mm2pixelsY
= pixel_height
/mm_height
;
1000 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
1001 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
1006 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
1007 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
1012 m_logicalScaleX
= mm2pixelsX
;
1013 m_logicalScaleY
= mm2pixelsY
;
1018 m_logicalScaleX
= (mm2pixelsX
/10.0);
1019 m_logicalScaleY
= (mm2pixelsY
/10.0);
1025 m_logicalScaleX
= 1.0;
1026 m_logicalScaleY
= 1.0;
1031 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
1032 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
1034 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1035 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1036 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1037 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1038 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1039 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1042 void wxDC::SetUserScale(double x
, double y
)
1047 SetMapMode(m_mappingMode
);
1050 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1052 m_signX
= xLeftRight
? 1 : -1;
1053 m_signY
= yBottomUp
? -1 : 1;
1055 SetMapMode(m_mappingMode
);
1058 void wxDC::SetSystemScale(double x
, double y
)
1063 SetMapMode(m_mappingMode
);
1066 void wxDC::SetLogicalOrigin(long x
, long y
)
1068 m_logicalOriginX
= x
;
1069 m_logicalOriginY
= y
;
1071 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1074 void wxDC::SetDeviceOrigin(long x
, long y
)
1076 m_deviceOriginX
= x
;
1077 m_deviceOriginY
= y
;
1079 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1082 // ---------------------------------------------------------------------------
1083 // coordinates transformations
1084 // ---------------------------------------------------------------------------
1086 long wxDCBase::DeviceToLogicalX(long x
) const
1088 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1091 long wxDCBase::DeviceToLogicalXRel(long x
) const
1093 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1096 long wxDCBase::DeviceToLogicalY(long y
) const
1098 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1101 long wxDCBase::DeviceToLogicalYRel(long y
) const
1103 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1106 long wxDCBase::LogicalToDeviceX(long x
) const
1108 return (long) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1111 long wxDCBase::LogicalToDeviceXRel(long x
) const
1113 return (long) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1116 long wxDCBase::LogicalToDeviceY(long y
) const
1118 return (long) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1121 long wxDCBase::LogicalToDeviceYRel(long y
) const
1123 return (long) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1126 // ---------------------------------------------------------------------------
1128 // ---------------------------------------------------------------------------
1129 bool wxDC::DoBlit(long xdest
, long ydest
, long width
, long height
,
1130 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1132 long xdest1
= xdest
;
1133 long ydest1
= ydest
;
1137 // Chris Breeze 18/5/98: use text foreground/background colours
1138 // when blitting from 1-bit bitmaps
1139 COLORREF old_textground
= ::GetTextColor(GetHdc());
1140 COLORREF old_background
= ::GetBkColor(GetHdc());
1141 if (m_textForegroundColour
.Ok())
1143 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1145 if (m_textBackgroundColour
.Ok())
1147 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1150 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1151 rop
== wxCLEAR
? WHITENESS
:
1152 rop
== wxSET
? BLACKNESS
:
1153 rop
== wxINVERT
? DSTINVERT
:
1154 rop
== wxAND
? MERGECOPY
:
1155 rop
== wxOR
? MERGEPAINT
:
1156 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1157 rop
== wxXOR
? SRCINVERT
:
1158 rop
== wxOR_REVERSE
? MERGEPAINT
:
1159 rop
== wxAND_REVERSE
? SRCERASE
:
1160 rop
== wxSRC_OR
? SRCPAINT
:
1161 rop
== wxSRC_AND
? SRCAND
:
1164 bool success
= TRUE
;
1165 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1169 // Not implemented under Win95 (or maybe a specific device?)
1170 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1171 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1181 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1182 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1183 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1184 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1185 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1186 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1187 ::SelectObject(dc_mask
, 0);
1188 ::DeleteDC(dc_mask
);
1190 // New code from Chris Breeze, 15/7/98
1191 // Blit bitmap with mask
1193 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1195 // If we are printing source colours are screen colours
1196 // not printer colours and so we need copy the bitmap
1199 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1200 HDC dc_src
= (HDC
) source
->m_hDC
;
1202 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1203 for (int x
= 0; x
< width
; x
++)
1205 for (int y
= 0; y
< height
; y
++)
1207 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1210 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1211 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1212 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1213 ::FillRect(GetHdc(), &rect
, brush
);
1214 ::DeleteObject(brush
);
1218 ::SelectObject(dc_mask
, 0);
1219 ::DeleteDC(dc_mask
);
1223 // create a temp buffer bitmap and DCs to access it and the mask
1224 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1225 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1226 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1227 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1228 ::SelectObject(dc_buffer
, buffer_bmap
);
1230 // copy dest to buffer
1231 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1232 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1234 // copy src to buffer using selected raster op
1235 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1236 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1238 // set masked area in buffer to BLACK (pixel value 0)
1239 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1240 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1241 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1242 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1244 // set unmasked area in dest to BLACK
1245 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1246 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1247 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1248 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1249 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1250 ::SetTextColor(GetHdc(), prevCol
);
1252 // OR buffer to dest
1253 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1254 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1256 // tidy up temporary DCs and bitmap
1257 ::SelectObject(dc_mask
, 0);
1258 ::DeleteDC(dc_mask
);
1259 ::SelectObject(dc_buffer
, 0);
1260 ::DeleteDC(dc_buffer
);
1261 ::DeleteObject(buffer_bmap
);
1267 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1269 // If we are printing, source colours are screen colours
1270 // not printer colours and so we need copy the bitmap
1272 HDC dc_src
= (HDC
) source
->m_hDC
;
1274 for (int x
= 0; x
< width
; x
++)
1276 for (int y
= 0; y
< height
; y
++)
1278 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1279 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1280 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1281 ::FillRect(GetHdc(), &rect
, brush
);
1282 ::DeleteObject(brush
);
1288 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1289 xsrc1
, ysrc1
, dwRop
) != 0);
1292 ::SetTextColor(GetHdc(), old_textground
);
1293 ::SetBkColor(GetHdc(), old_background
);
1298 void wxDC::DoGetSize(int *w
, int *h
) const
1300 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1301 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1304 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1306 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1307 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1310 wxSize
wxDC::GetPPI() const
1312 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1313 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1315 return wxSize(x
, y
);
1318 // For use by wxWindows only, unless custom units are required.
1319 void wxDC::SetLogicalScale(double x
, double y
)
1321 m_logicalScaleX
= x
;
1322 m_logicalScaleY
= y
;
1325 #if WXWIN_COMPATIBILITY
1326 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1327 float *descent
, float *externalLeading
,
1328 wxFont
*theFont
, bool use16bit
) const
1330 long x1
, y1
, descent1
, externalLeading1
;
1331 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1334 *descent
= descent1
;
1335 if (externalLeading
)
1336 *externalLeading
= externalLeading1
;
1340 // ---------------------------------------------------------------------------
1341 // spline drawing code
1342 // ---------------------------------------------------------------------------
1346 class wxSpline
: public wxObject
1352 wxSpline(wxList
*list
);
1353 void DeletePoints();
1355 // Doesn't delete points
1359 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1361 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1362 double a3
, double b3
, double a4
, double b4
);
1363 void wx_clear_stack();
1364 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1365 double *y3
, double *x4
, double *y4
);
1366 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1367 double x4
, double y4
);
1368 static bool wx_spline_add_point(double x
, double y
);
1369 static void wx_spline_draw_point_array(wxDC
*dc
);
1370 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1372 void wxDC::DoDrawSpline(wxList
*list
)
1374 wxSpline
spline(list
);
1376 wx_draw_open_spline(this, &spline
);
1379 wxList wx_spline_point_list
;
1381 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1384 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1385 double x1
, y1
, x2
, y2
;
1387 wxNode
*node
= spline
->points
->First();
1388 p
= (wxPoint
*)node
->Data();
1393 node
= node
->Next();
1394 p
= (wxPoint
*)node
->Data();
1398 cx1
= (double)((x1
+ x2
) / 2);
1399 cy1
= (double)((y1
+ y2
) / 2);
1400 cx2
= (double)((cx1
+ x2
) / 2);
1401 cy2
= (double)((cy1
+ y2
) / 2);
1403 wx_spline_add_point(x1
, y1
);
1405 while ((node
= node
->Next()) != NULL
)
1407 p
= (wxPoint
*)node
->Data();
1412 cx4
= (double)(x1
+ x2
) / 2;
1413 cy4
= (double)(y1
+ y2
) / 2;
1414 cx3
= (double)(x1
+ cx4
) / 2;
1415 cy3
= (double)(y1
+ cy4
) / 2;
1417 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1421 cx2
= (double)(cx1
+ x2
) / 2;
1422 cy2
= (double)(cy1
+ y2
) / 2;
1425 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1426 wx_spline_add_point(x2
, y2
);
1428 wx_spline_draw_point_array(dc
);
1432 /********************* CURVES FOR SPLINES *****************************
1434 The following spline drawing routine is from
1436 "An Algorithm for High-Speed Curve Generation"
1437 by George Merrill Chaikin,
1438 Computer Graphics and Image Processing, 3, Academic Press,
1443 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1444 Computer Graphics and Image Processing, 4, Academic Press,
1447 ***********************************************************************/
1449 #define half(z1, z2) ((z1+z2)/2.0)
1452 /* iterative version */
1454 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1457 register double xmid
, ymid
;
1458 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1461 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1463 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1464 xmid
= (double)half(x2
, x3
);
1465 ymid
= (double)half(y2
, y3
);
1466 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1467 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1468 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1469 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1471 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1472 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1473 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1474 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1480 /* utilities used by spline drawing routines */
1483 typedef struct wx_spline_stack_struct
{
1484 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1488 #define SPLINE_STACK_DEPTH 20
1489 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1490 static Stack
*wx_stack_top
;
1491 static int wx_stack_count
;
1493 void wx_clear_stack()
1495 wx_stack_top
= wx_spline_stack
;
1499 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1501 wx_stack_top
->x1
= x1
;
1502 wx_stack_top
->y1
= y1
;
1503 wx_stack_top
->x2
= x2
;
1504 wx_stack_top
->y2
= y2
;
1505 wx_stack_top
->x3
= x3
;
1506 wx_stack_top
->y3
= y3
;
1507 wx_stack_top
->x4
= x4
;
1508 wx_stack_top
->y4
= y4
;
1513 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1514 double *x3
, double *y3
, double *x4
, double *y4
)
1516 if (wx_stack_count
== 0)
1520 *x1
= wx_stack_top
->x1
;
1521 *y1
= wx_stack_top
->y1
;
1522 *x2
= wx_stack_top
->x2
;
1523 *y2
= wx_stack_top
->y2
;
1524 *x3
= wx_stack_top
->x3
;
1525 *y3
= wx_stack_top
->y3
;
1526 *x4
= wx_stack_top
->x4
;
1527 *y4
= wx_stack_top
->y4
;
1531 static bool wx_spline_add_point(double x
, double y
)
1533 wxPoint
*point
= new wxPoint
;
1536 wx_spline_point_list
.Append((wxObject
*)point
);
1540 static void wx_spline_draw_point_array(wxDC
*dc
)
1542 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1543 wxNode
*node
= wx_spline_point_list
.First();
1546 wxPoint
*point
= (wxPoint
*)node
->Data();
1549 node
= wx_spline_point_list
.First();
1553 wxSpline::wxSpline(wxList
*list
)
1558 wxSpline::~wxSpline()
1562 void wxSpline::DeletePoints()
1564 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1566 wxPoint
*point
= (wxPoint
*)node
->Data();
1574 #endif // wxUSE_SPLINES