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/msw/private.h"
37 #include "wx/dialog.h"
39 #include "wx/bitmap.h"
40 #include "wx/dcmemory.h"
44 #include "wx/dcprint.h"
49 #if wxUSE_COMMON_DIALOGS
57 #if !USE_SHARED_LIBRARY
58 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
61 // ---------------------------------------------------------------------------
63 // ---------------------------------------------------------------------------
65 static const int VIEWPORT_EXTENT
= 1000;
67 static const int MM_POINTS
= 9;
68 static const int MM_METRIC
= 10;
70 // ---------------------------------------------------------------------------
72 // ---------------------------------------------------------------------------
76 #define XLOG2DEV(x) (x)
77 #define YLOG2DEV(y) (y)
80 #define XLOG2DEVREL(x) (x)
81 #define YLOG2DEVREL(y) (y)
85 #define XDEV2LOG(x) (x)
87 #define YDEV2LOG(y) (y)
90 #define XDEV2LOGREL(x) (x)
91 #define YDEV2LOGREL(y) (y)
94 * Have the same macros as for XView but not for every operation:
95 * just for calculating window/viewport extent (a better way of scaling).
100 #define MS_XLOG2DEV(x) LogicalToDevice(x)
102 #define MS_YLOG2DEV(y) LogicalToDevice(y)
105 #define MS_XLOG2DEVREL(x) LogicalToDeviceXRel(x)
106 #define MS_YLOG2DEVREL(y) LogicalToDeviceYRel(y)
110 #define MS_XDEV2LOG(x) DeviceToLogicalX(x)
112 #define MS_YDEV2LOG(y) DeviceToLogicalY(y)
115 #define MS_XDEV2LOGREL(x) DeviceToLogicalXRel(x)
116 #define MS_YDEV2LOGREL(y) DeviceToLogicalYRel(y)
118 #define YSCALE(y) (yorigin - (y))
120 #define wx_round(a) (int)((a)+.5)
122 // ===========================================================================
124 // ===========================================================================
126 // ---------------------------------------------------------------------------
128 // ---------------------------------------------------------------------------
130 // Default constructor
144 m_windowExtX
= VIEWPORT_EXTENT
;
145 m_windowExtY
= VIEWPORT_EXTENT
;
154 SelectOldObjects(m_hDC
);
156 if ( m_canvas
== NULL
)
157 ::DeleteDC(GetHdc());
159 ::ReleaseDC((HWND
)m_canvas
->GetHWND(), GetHdc());
165 // This will select current objects out of the DC,
166 // which is what you have to do before deleting the
168 void wxDC::SelectOldObjects(WXHDC dc
)
174 ::SelectObject((HDC
) dc
, (HBITMAP
) m_oldBitmap
);
175 if (m_selectedBitmap
.Ok())
177 m_selectedBitmap
.SetSelectedInto(NULL
);
183 ::SelectObject((HDC
) dc
, (HPEN
) m_oldPen
);
188 ::SelectObject((HDC
) dc
, (HBRUSH
) m_oldBrush
);
193 ::SelectObject((HDC
) dc
, (HFONT
) m_oldFont
);
198 ::SelectPalette((HDC
) dc
, (HPALETTE
) m_oldPalette
, TRUE
);
203 m_brush
= wxNullBrush
;
205 m_palette
= wxNullPalette
;
207 m_backgroundBrush
= wxNullBrush
;
208 m_selectedBitmap
= wxNullBitmap
;
211 // ---------------------------------------------------------------------------
213 // ---------------------------------------------------------------------------
215 void wxDC::DoSetClippingRegion(long cx
, long cy
, long cw
, long ch
)
220 m_clipX2
= (int)(cx
+ cw
);
221 m_clipY2
= (int)(cy
+ ch
);
223 DoClipping((WXHDC
) m_hDC
);
226 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
228 wxCHECK_RET( region
.GetHRGN(), _T("invalid clipping region") );
230 wxRect box
= region
.GetBox();
235 m_clipX2
= box
.x
+ box
.width
;
236 m_clipY2
= box
.y
+ box
.height
;
239 SelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN());
241 ExtSelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN(), RGN_AND
);
245 void wxDC::DoClipping(WXHDC dc
)
247 if (m_clipping
&& dc
)
249 IntersectClipRect((HDC
) dc
, XLOG2DEV(m_clipX1
), YLOG2DEV(m_clipY1
),
250 XLOG2DEV(m_clipX2
), YLOG2DEV(m_clipY2
));
254 void wxDC::DestroyClippingRegion()
256 if (m_clipping
&& m_hDC
)
258 // TODO: this should restore the previous clipping region,
259 // so that OnPaint processing works correctly, and the update clipping region
260 // doesn't get destroyed after the first DestroyClippingRegion.
261 HRGN rgn
= CreateRectRgn(0, 0, 32000, 32000);
262 SelectClipRgn(GetHdc(), rgn
);
268 // ---------------------------------------------------------------------------
269 // query capabilities
270 // ---------------------------------------------------------------------------
272 bool wxDC::CanDrawBitmap() const
277 bool wxDC::CanGetTextExtent() const
279 // What sort of display is it?
280 int technology
= ::GetDeviceCaps(GetHdc(), TECHNOLOGY
);
282 return (technology
== DT_RASDISPLAY
) || (technology
== DT_RASPRINTER
);
285 int wxDC::GetDepth() const
287 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL
);
290 // ---------------------------------------------------------------------------
292 // ---------------------------------------------------------------------------
298 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
299 else if (m_selectedBitmap
.Ok())
301 rect
.left
= 0; rect
.top
= 0;
302 rect
.right
= m_selectedBitmap
.GetWidth();
303 rect
.bottom
= m_selectedBitmap
.GetHeight();
305 (void) ::SetMapMode(GetHdc(), MM_TEXT
);
307 DWORD colour
= GetBkColor(GetHdc());
308 HBRUSH brush
= CreateSolidBrush(colour
);
309 FillRect(GetHdc(), &rect
, brush
);
312 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
313 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
314 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
315 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
316 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
319 void wxDC::DoFloodFill(long x
, long y
, const wxColour
& col
, int style
)
321 (void)ExtFloodFill(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
323 style
== wxFLOOD_SURFACE
? FLOODFILLSURFACE
326 CalcBoundingBox(x
, y
);
329 bool wxDC::DoGetPixel(long x
, long y
, wxColour
*col
) const
331 // added by steve 29.12.94 (copied from DrawPoint)
332 // returns TRUE for pixels in the color of the current pen
333 // and FALSE for all other pixels colors
334 // if col is non-NULL return the color of the pixel
336 // get the color of the pixel
337 COLORREF pixelcolor
= ::GetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
));
338 // get the color of the pen
339 COLORREF pencolor
= 0x00ffffff;
342 pencolor
= m_pen
.GetColour().GetPixel();
345 // return the color of the pixel
347 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
349 // check, if color of the pixels is the same as the color
350 // of the current pen
351 return(pixelcolor
==pencolor
);
354 void wxDC::DoCrossHair(long x
, long y
)
356 long x1
= x
-VIEWPORT_EXTENT
;
357 long y1
= y
-VIEWPORT_EXTENT
;
358 long x2
= x
+VIEWPORT_EXTENT
;
359 long y2
= y
+VIEWPORT_EXTENT
;
361 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
362 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y
));
364 (void)MoveToEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
365 (void)LineTo(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y2
));
367 CalcBoundingBox(x1
, y1
);
368 CalcBoundingBox(x2
, y2
);
371 void wxDC::DoDrawLine(long x1
, long y1
, long x2
, long y2
)
373 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
374 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y2
));
376 /* MATTHEW: [6] New normalization */
377 #if WX_STANDARD_GRAPHICS
378 (void)LineTo(GetHdc(), XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
381 CalcBoundingBox(x1
, y1
);
382 CalcBoundingBox(x2
, y2
);
385 void wxDC::DoDrawArc(long x1
,long y1
,long x2
,long y2
, long xc
, long yc
)
389 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
390 if (x1
==x2
&& x2
==y2
)
392 DrawEllipse(xc
,yc
,(long)(radius
*2.0),(long)(radius
*2.0));
396 long xx1
= XLOG2DEV(x1
);
397 long yy1
= YLOG2DEV(y1
);
398 long xx2
= XLOG2DEV(x2
);
399 long yy2
= YLOG2DEV(y2
);
400 long xxc
= XLOG2DEV(xc
);
401 long yyc
= YLOG2DEV(yc
);
402 long ray
= (long) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
)));
404 (void)MoveToEx(GetHdc(), (int) xx1
, (int) yy1
, NULL
);
405 long xxx1
= (long) (xxc
-ray
);
406 long yyy1
= (long) (yyc
-ray
);
407 long xxx2
= (long) (xxc
+ray
);
408 long yyy2
= (long) (yyc
+ray
);
409 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
411 // Have to add 1 to bottom-right corner of rectangle
412 // to make semi-circles look right (crooked line otherwise).
413 // Unfortunately this is not a reliable method, depends
414 // on the size of shape.
415 // TODO: figure out why this happens!
416 Pie(GetHdc(),xxx1
,yyy1
,xxx2
+1,yyy2
+1,
420 Arc(GetHdc(),xxx1
,yyy1
,xxx2
,yyy2
,
423 CalcBoundingBox((xc
-radius
), (yc
-radius
));
424 CalcBoundingBox((xc
+radius
), (yc
+radius
));
427 void wxDC::DoDrawPoint(long x
, long y
)
429 COLORREF color
= 0x00ffffff;
432 color
= m_pen
.GetColour().GetPixel();
435 SetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), color
);
437 CalcBoundingBox(x
, y
);
440 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], long xoffset
, long yoffset
,int fillStyle
)
442 // Do things less efficiently if we have offsets
443 if (xoffset
!= 0 || yoffset
!= 0)
445 POINT
*cpoints
= new POINT
[n
];
447 for (i
= 0; i
< n
; i
++)
449 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
450 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
452 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
454 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
455 (void)Polygon(GetHdc(), cpoints
, n
);
456 SetPolyFillMode(GetHdc(),prev
);
462 for (i
= 0; i
< n
; i
++)
463 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
465 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
466 (void)Polygon(GetHdc(), (POINT
*) points
, n
);
467 SetPolyFillMode(GetHdc(),prev
);
471 void wxDC::DoDrawLines(int n
, wxPoint points
[], long xoffset
, long yoffset
)
473 // Do things less efficiently if we have offsets
474 if (xoffset
!= 0 || yoffset
!= 0)
476 POINT
*cpoints
= new POINT
[n
];
478 for (i
= 0; i
< n
; i
++)
480 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
481 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
483 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
485 (void)Polyline(GetHdc(), cpoints
, n
);
491 for (i
= 0; i
< n
; i
++)
492 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
494 (void)Polyline(GetHdc(), (POINT
*) points
, n
);
498 void wxDC::DoDrawRectangle(long x
, long y
, long width
, long height
)
501 long y2
= y
+ height
;
503 /* MATTHEW: [6] new normalization */
504 #if WX_STANDARD_GRAPHICS
505 bool do_brush
, do_pen
;
507 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
508 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
511 HPEN orig_pen
= NULL
;
513 if (do_pen
|| !m_pen
.Ok())
514 orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
516 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
517 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
519 if (do_pen
|| !m_pen
.Ok())
520 ::SelectObject(GetHdc() , orig_pen
);
523 HBRUSH orig_brush
= NULL
;
525 if (do_brush
|| !m_brush
.Ok())
526 orig_brush
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
528 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
529 XLOG2DEV(x2
), YLOG2DEV(y2
));
531 if (do_brush
|| !m_brush
.Ok())
532 ::SelectObject(GetHdc(), orig_brush
);
535 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
538 CalcBoundingBox(x
, y
);
539 CalcBoundingBox(x2
, y2
);
542 void wxDC::DoDrawRoundedRectangle(long x
, long y
, long width
, long height
, double radius
)
544 // Now, a negative radius value is interpreted to mean
545 // 'the proportion of the smallest X or Y dimension'
549 double smallest
= 0.0;
554 radius
= (- radius
* smallest
);
558 long y2
= (y
+height
);
560 (void)RoundRect(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
561 YLOG2DEV(y2
), 2*XLOG2DEV(radius
), 2*YLOG2DEV(radius
));
563 CalcBoundingBox(x
, y
);
564 CalcBoundingBox(x2
, y2
);
567 void wxDC::DoDrawEllipse(long x
, long y
, long width
, long height
)
570 long y2
= (y
+height
);
572 (void)Ellipse(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
574 CalcBoundingBox(x
, y
);
575 CalcBoundingBox(x2
, y2
);
578 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
579 void wxDC::DoDrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
)
584 const double deg2rad
= 3.14159265359 / 180.0;
585 int rx1
= XLOG2DEV(x
+w
/2);
586 int ry1
= YLOG2DEV(y
+h
/2);
589 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
590 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
591 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
592 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
594 // draw pie with NULL_PEN first and then outline otherwise a line is
595 // drawn from the start and end points to the centre
596 HPEN orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
599 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
604 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
605 rx1
, ry1
-1, rx2
, ry2
-1);
607 ::SelectObject(GetHdc(), orig_pen
);
608 (void)Arc(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
611 CalcBoundingBox(x
, y
);
612 CalcBoundingBox(x2
, y2
);
615 void wxDC::DoDrawIcon(const wxIcon
& icon
, long x
, long y
)
617 #if defined(__WIN32__) && !defined(__SC__) && !defined(__TWIN32__)
618 ::DrawIconEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON(),
619 icon
.GetWidth(), icon
.GetHeight(), 0, 0, DI_NORMAL
);
621 ::DrawIcon(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
624 CalcBoundingBox(x
, y
);
625 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
628 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, long x
, long y
, bool useMask
)
633 // If we're not drawing transparently, and not drawing to a printer,
634 // optimize this function to use Windows functions.
635 if (!useMask
&& !IsKindOf(CLASSINFO(wxPrinterDC
)))
638 HDC memdc
= ::CreateCompatibleDC( cdc
);
639 HBITMAP hbitmap
= (HBITMAP
) bmp
.GetHBITMAP( );
640 ::SelectObject( memdc
, hbitmap
);
641 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
642 ::SelectObject( memdc
, 0 );
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) (floor((x
) - m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1111 long wxDCBase::LogicalToDeviceXRel(long x
) const
1113 return (long) (floor(x
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1116 long wxDCBase::LogicalToDeviceY(long y
) const
1118 return (long) (floor((y
) - m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1121 long wxDCBase::LogicalToDeviceYRel(long y
) const
1123 return (long) (floor(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