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"
35 #include "wx/dialog.h"
37 #include "wx/bitmap.h"
38 #include "wx/dcmemory.h"
41 #include "wx/dcprint.h"
42 #include "wx/msw/private.h"
47 #if wxUSE_COMMON_DIALOGS
55 #if !USE_SHARED_LIBRARY
56 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
59 // ---------------------------------------------------------------------------
61 // ---------------------------------------------------------------------------
63 static const int VIEWPORT_EXTENT
= 1000;
65 static const int MM_POINTS
= 9;
66 static const int MM_METRIC
= 10;
68 // ---------------------------------------------------------------------------
70 // ---------------------------------------------------------------------------
74 #define XLOG2DEV(x) (x)
75 #define YLOG2DEV(y) (y)
78 #define XLOG2DEVREL(x) (x)
79 #define YLOG2DEVREL(y) (y)
83 #define XDEV2LOG(x) (x)
85 #define YDEV2LOG(y) (y)
88 #define XDEV2LOGREL(x) (x)
89 #define YDEV2LOGREL(y) (y)
92 * Have the same macros as for XView but not for every operation:
93 * just for calculating window/viewport extent (a better way of scaling).
98 #define MS_XLOG2DEV(x) LogicalToDevice(x)
100 #define MS_YLOG2DEV(y) LogicalToDevice(y)
103 #define MS_XLOG2DEVREL(x) LogicalToDeviceXRel(x)
104 #define MS_YLOG2DEVREL(y) LogicalToDeviceYRel(y)
108 #define MS_XDEV2LOG(x) DeviceToLogicalX(x)
110 #define MS_YDEV2LOG(y) DeviceToLogicalY(y)
113 #define MS_XDEV2LOGREL(x) DeviceToLogicalXRel(x)
114 #define MS_YDEV2LOGREL(y) DeviceToLogicalYRel(y)
116 #define YSCALE(y) (yorigin - (y))
118 #define wx_round(a) (int)((a)+.5)
120 // ===========================================================================
122 // ===========================================================================
124 // ---------------------------------------------------------------------------
126 // ---------------------------------------------------------------------------
128 // Default constructor
142 m_windowExtX
= VIEWPORT_EXTENT
;
143 m_windowExtY
= VIEWPORT_EXTENT
;
152 SelectOldObjects(m_hDC
);
154 if ( m_canvas
== NULL
)
155 ::DeleteDC(GetHdc());
157 ::ReleaseDC((HWND
)m_canvas
->GetHWND(), GetHdc());
163 // This will select current objects out of the DC,
164 // which is what you have to do before deleting the
166 void wxDC::SelectOldObjects(WXHDC dc
)
172 ::SelectObject((HDC
) dc
, (HBITMAP
) m_oldBitmap
);
173 if (m_selectedBitmap
.Ok())
175 m_selectedBitmap
.SetSelectedInto(NULL
);
181 ::SelectObject((HDC
) dc
, (HPEN
) m_oldPen
);
186 ::SelectObject((HDC
) dc
, (HBRUSH
) m_oldBrush
);
191 ::SelectObject((HDC
) dc
, (HFONT
) m_oldFont
);
196 ::SelectPalette((HDC
) dc
, (HPALETTE
) m_oldPalette
, TRUE
);
201 m_brush
= wxNullBrush
;
203 m_palette
= wxNullPalette
;
205 m_backgroundBrush
= wxNullBrush
;
206 m_selectedBitmap
= wxNullBitmap
;
209 // ---------------------------------------------------------------------------
211 // ---------------------------------------------------------------------------
213 void wxDC::DoSetClippingRegion(long cx
, long cy
, long cw
, long ch
)
218 m_clipX2
= (int)(cx
+ cw
);
219 m_clipY2
= (int)(cy
+ ch
);
221 DoClipping((WXHDC
) m_hDC
);
224 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
226 wxCHECK_RET( region
.GetHRGN(), _T("invalid clipping region") );
228 wxRect box
= region
.GetBox();
233 m_clipX2
= box
.x
+ box
.width
;
234 m_clipY2
= box
.y
+ box
.height
;
237 SelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN());
239 ExtSelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN(), RGN_AND
);
243 void wxDC::DoClipping(WXHDC dc
)
245 if (m_clipping
&& dc
)
247 IntersectClipRect((HDC
) dc
, XLOG2DEV(m_clipX1
), YLOG2DEV(m_clipY1
),
248 XLOG2DEV(m_clipX2
), YLOG2DEV(m_clipY2
));
252 void wxDC::DestroyClippingRegion()
254 if (m_clipping
&& m_hDC
)
256 // TODO: this should restore the previous clipping region,
257 // so that OnPaint processing works correctly, and the update clipping region
258 // doesn't get destroyed after the first DestroyClippingRegion.
259 HRGN rgn
= CreateRectRgn(0, 0, 32000, 32000);
260 SelectClipRgn(GetHdc(), rgn
);
266 // ---------------------------------------------------------------------------
267 // query capabilities
268 // ---------------------------------------------------------------------------
270 bool wxDC::CanDrawBitmap() const
275 bool wxDC::CanGetTextExtent() const
277 // What sort of display is it?
278 int technology
= ::GetDeviceCaps(GetHdc(), TECHNOLOGY
);
280 return (technology
== DT_RASDISPLAY
) || (technology
== DT_RASPRINTER
);
283 int wxDC::GetDepth() const
285 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL
);
288 // ---------------------------------------------------------------------------
290 // ---------------------------------------------------------------------------
296 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
297 else if (m_selectedBitmap
.Ok())
299 rect
.left
= 0; rect
.top
= 0;
300 rect
.right
= m_selectedBitmap
.GetWidth();
301 rect
.bottom
= m_selectedBitmap
.GetHeight();
303 (void) ::SetMapMode(GetHdc(), MM_TEXT
);
305 DWORD colour
= GetBkColor(GetHdc());
306 HBRUSH brush
= CreateSolidBrush(colour
);
307 FillRect(GetHdc(), &rect
, brush
);
310 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
311 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
312 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
313 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
314 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
317 void wxDC::DoFloodFill(long x
, long y
, const wxColour
& col
, int style
)
319 (void)ExtFloodFill(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
321 style
== wxFLOOD_SURFACE
? FLOODFILLSURFACE
324 CalcBoundingBox(x
, y
);
327 bool wxDC::DoGetPixel(long x
, long y
, wxColour
*col
) const
329 // added by steve 29.12.94 (copied from DrawPoint)
330 // returns TRUE for pixels in the color of the current pen
331 // and FALSE for all other pixels colors
332 // if col is non-NULL return the color of the pixel
334 // get the color of the pixel
335 COLORREF pixelcolor
= ::GetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
));
336 // get the color of the pen
337 COLORREF pencolor
= 0x00ffffff;
340 pencolor
= m_pen
.GetColour().GetPixel();
343 // return the color of the pixel
345 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
347 // check, if color of the pixels is the same as the color
348 // of the current pen
349 return(pixelcolor
==pencolor
);
352 void wxDC::DoCrossHair(long x
, long y
)
354 long x1
= x
-VIEWPORT_EXTENT
;
355 long y1
= y
-VIEWPORT_EXTENT
;
356 long x2
= x
+VIEWPORT_EXTENT
;
357 long y2
= y
+VIEWPORT_EXTENT
;
359 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
360 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y
));
362 (void)MoveToEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
363 (void)LineTo(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y2
));
365 CalcBoundingBox(x1
, y1
);
366 CalcBoundingBox(x2
, y2
);
369 void wxDC::DoDrawLine(long x1
, long y1
, long x2
, long y2
)
371 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
372 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y2
));
374 /* MATTHEW: [6] New normalization */
375 #if WX_STANDARD_GRAPHICS
376 (void)LineTo(GetHdc(), XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
379 CalcBoundingBox(x1
, y1
);
380 CalcBoundingBox(x2
, y2
);
383 void wxDC::DoDrawArc(long x1
,long y1
,long x2
,long y2
, long xc
, long yc
)
387 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
388 if (x1
==x2
&& x2
==y2
)
390 DrawEllipse(xc
,yc
,(long)(radius
*2.0),(long)(radius
*2.0));
394 long xx1
= XLOG2DEV(x1
);
395 long yy1
= YLOG2DEV(y1
);
396 long xx2
= XLOG2DEV(x2
);
397 long yy2
= YLOG2DEV(y2
);
398 long xxc
= XLOG2DEV(xc
);
399 long yyc
= YLOG2DEV(yc
);
400 long ray
= (long) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
)));
402 (void)MoveToEx(GetHdc(), (int) xx1
, (int) yy1
, NULL
);
403 long xxx1
= (long) (xxc
-ray
);
404 long yyy1
= (long) (yyc
-ray
);
405 long xxx2
= (long) (xxc
+ray
);
406 long yyy2
= (long) (yyc
+ray
);
407 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
409 // Have to add 1 to bottom-right corner of rectangle
410 // to make semi-circles look right (crooked line otherwise).
411 // Unfortunately this is not a reliable method, depends
412 // on the size of shape.
413 // TODO: figure out why this happens!
414 Pie(GetHdc(),xxx1
,yyy1
,xxx2
+1,yyy2
+1,
418 Arc(GetHdc(),xxx1
,yyy1
,xxx2
,yyy2
,
421 CalcBoundingBox((xc
-radius
), (yc
-radius
));
422 CalcBoundingBox((xc
+radius
), (yc
+radius
));
425 void wxDC::DoDrawPoint(long x
, long y
)
427 COLORREF color
= 0x00ffffff;
430 color
= m_pen
.GetColour().GetPixel();
433 SetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), color
);
435 CalcBoundingBox(x
, y
);
438 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], long xoffset
, long yoffset
,int fillStyle
)
440 // Do things less efficiently if we have offsets
441 if (xoffset
!= 0 || yoffset
!= 0)
443 POINT
*cpoints
= new POINT
[n
];
445 for (i
= 0; i
< n
; i
++)
447 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
448 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
450 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
452 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
453 (void)Polygon(GetHdc(), cpoints
, n
);
454 SetPolyFillMode(GetHdc(),prev
);
460 for (i
= 0; i
< n
; i
++)
461 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
463 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
464 (void)Polygon(GetHdc(), (POINT
*) points
, n
);
465 SetPolyFillMode(GetHdc(),prev
);
469 void wxDC::DoDrawLines(int n
, wxPoint points
[], long xoffset
, long yoffset
)
471 // Do things less efficiently if we have offsets
472 if (xoffset
!= 0 || yoffset
!= 0)
474 POINT
*cpoints
= new POINT
[n
];
476 for (i
= 0; i
< n
; i
++)
478 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
479 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
481 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
483 (void)Polyline(GetHdc(), cpoints
, n
);
489 for (i
= 0; i
< n
; i
++)
490 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
492 (void)Polyline(GetHdc(), (POINT
*) points
, n
);
496 void wxDC::DoDrawRectangle(long x
, long y
, long width
, long height
)
499 long y2
= y
+ height
;
501 /* MATTHEW: [6] new normalization */
502 #if WX_STANDARD_GRAPHICS
503 bool do_brush
, do_pen
;
505 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
506 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
509 HPEN orig_pen
= NULL
;
511 if (do_pen
|| !m_pen
.Ok())
512 orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
514 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
515 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
517 if (do_pen
|| !m_pen
.Ok())
518 ::SelectObject(GetHdc() , orig_pen
);
521 HBRUSH orig_brush
= NULL
;
523 if (do_brush
|| !m_brush
.Ok())
524 orig_brush
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
526 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
527 XLOG2DEV(x2
), YLOG2DEV(y2
));
529 if (do_brush
|| !m_brush
.Ok())
530 ::SelectObject(GetHdc(), orig_brush
);
533 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
536 CalcBoundingBox(x
, y
);
537 CalcBoundingBox(x2
, y2
);
540 void wxDC::DoDrawRoundedRectangle(long x
, long y
, long width
, long height
, double radius
)
542 // Now, a negative radius value is interpreted to mean
543 // 'the proportion of the smallest X or Y dimension'
547 double smallest
= 0.0;
552 radius
= (- radius
* smallest
);
556 long y2
= (y
+height
);
558 (void)RoundRect(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
559 YLOG2DEV(y2
), 2*XLOG2DEV(radius
), 2*YLOG2DEV(radius
));
561 CalcBoundingBox(x
, y
);
562 CalcBoundingBox(x2
, y2
);
565 void wxDC::DoDrawEllipse(long x
, long y
, long width
, long height
)
568 long y2
= (y
+height
);
570 (void)Ellipse(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
572 CalcBoundingBox(x
, y
);
573 CalcBoundingBox(x2
, y2
);
576 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
577 void wxDC::DoDrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
)
582 const double deg2rad
= 3.14159265359 / 180.0;
583 int rx1
= XLOG2DEV(x
+w
/2);
584 int ry1
= YLOG2DEV(y
+h
/2);
587 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
588 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
589 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
590 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
592 // draw pie with NULL_PEN first and then outline otherwise a line is
593 // drawn from the start and end points to the centre
594 HPEN orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
597 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
602 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
603 rx1
, ry1
-1, rx2
, ry2
-1);
605 ::SelectObject(GetHdc(), orig_pen
);
606 (void)Arc(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
609 CalcBoundingBox(x
, y
);
610 CalcBoundingBox(x2
, y2
);
613 void wxDC::DoDrawIcon(const wxIcon
& icon
, long x
, long y
)
615 #if defined(__WIN32__) && !defined(__SC__) && !defined(__TWIN32__)
616 ::DrawIconEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON(),
617 icon
.GetWidth(), icon
.GetHeight(), 0, 0, DI_NORMAL
);
619 ::DrawIcon(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
622 CalcBoundingBox(x
, y
);
623 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
626 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, long x
, long y
, bool useMask
)
631 // If we're not drawing transparently, and not drawing to a printer,
632 // optimize this function to use Windows functions.
633 if (!useMask
&& !IsKindOf(CLASSINFO(wxPrinterDC
)))
636 HDC memdc
= ::CreateCompatibleDC( cdc
);
637 HBITMAP hbitmap
= (HBITMAP
) bmp
.GetHBITMAP( );
638 ::SelectObject( memdc
, hbitmap
);
639 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
640 ::SelectObject( memdc
, 0 );
645 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
647 memDC
.SelectObject(bmp
);
649 /* Not sure if we need this. The mask should leave the
650 * masked areas as per the original background of this DC.
653 // There might be transparent areas, so make these
654 // the same colour as this DC
655 memDC.SetBackground(* GetBackground());
659 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
661 memDC
.SelectObject(wxNullBitmap
);
665 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
667 if (m_textForegroundColour
.Ok())
668 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
670 DWORD old_background
= 0;
671 if (m_textBackgroundColour
.Ok())
673 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
676 if (m_backgroundMode
== wxTRANSPARENT
)
677 SetBkMode(GetHdc(), TRANSPARENT
);
679 SetBkMode(GetHdc(), OPAQUE
);
681 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (char *) (const char *)text
, strlen((const char *)text
));
683 if (m_textBackgroundColour
.Ok())
684 (void)SetBkColor(GetHdc(), old_background
);
686 CalcBoundingBox(x
, y
);
689 GetTextExtent(text
, &w
, &h
);
690 CalcBoundingBox((x
+ w
), (y
+ h
));
693 // ---------------------------------------------------------------------------
695 // ---------------------------------------------------------------------------
697 void wxDC::SetPalette(const wxPalette
& palette
)
699 // Set the old object temporarily, in case the assignment deletes an object
700 // that's not yet selected out.
703 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
711 // Setting a NULL colourmap is a way of restoring
712 // the original colourmap
715 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
722 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
724 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
726 m_oldPalette
= (WXHPALETTE
) oldPal
;
728 ::RealizePalette(GetHdc());
732 void wxDC::SetFont(const wxFont
& the_font
)
734 // Set the old object temporarily, in case the assignment deletes an object
735 // that's not yet selected out.
738 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
747 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
751 if (m_font
.Ok() && m_font
.GetResourceHandle())
753 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
754 if (f
== (HFONT
) NULL
)
756 wxLogDebug("::SelectObject failed in wxDC::SetFont.");
759 m_oldFont
= (WXHFONT
) f
;
763 void wxDC::SetPen(const wxPen
& pen
)
765 // Set the old object temporarily, in case the assignment deletes an object
766 // that's not yet selected out.
769 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
778 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
784 if (m_pen
.GetResourceHandle())
786 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
788 m_oldPen
= (WXHPEN
) p
;
793 void wxDC::SetBrush(const wxBrush
& brush
)
795 // Set the old object temporarily, in case the assignment deletes an object
796 // that's not yet selected out.
799 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
808 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
814 if (m_brush
.GetResourceHandle())
817 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
819 m_oldBrush
= (WXHBRUSH
) b
;
824 void wxDC::SetBackground(const wxBrush
& brush
)
826 m_backgroundBrush
= brush
;
828 if (!m_backgroundBrush
.Ok())
833 bool customColours
= TRUE
;
834 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
835 // change background colours from the control-panel specified colours.
836 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
837 customColours
= FALSE
;
841 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
843 m_canvas
->SetTransparent(TRUE
);
847 // New behaviour, 10/2/99: setting the background brush of a DC
848 // doesn't affect the window background colour. However,
849 // I'm leaving in the transparency setting because it's needed by
850 // various controls (e.g. wxStaticText) to determine whether to draw
851 // transparently or not. TODO: maybe this should be a new function
852 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
854 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
855 m_canvas
->SetTransparent(FALSE
);
859 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
861 (void)SetBkColor(GetHdc(), new_color
);
865 void wxDC::SetBackgroundMode(int mode
)
867 m_backgroundMode
= mode
;
869 if (m_backgroundMode
== wxTRANSPARENT
)
870 ::SetBkMode(GetHdc(), TRANSPARENT
);
872 ::SetBkMode(GetHdc(), OPAQUE
);
875 void wxDC::SetLogicalFunction(int function
)
877 m_logicalFunction
= function
;
879 SetRop((WXHDC
) m_hDC
);
882 void wxDC::SetRop(WXHDC dc
)
884 if (!dc
|| m_logicalFunction
< 0)
888 // These may be wrong
889 switch (m_logicalFunction
)
891 // case wxXOR: c_rop = R2_XORPEN; break;
892 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
893 case wxINVERT
: c_rop
= R2_NOT
; break;
894 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
895 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
896 case wxCLEAR
: c_rop
= R2_WHITE
; break;
897 case wxSET
: c_rop
= R2_BLACK
; break;
898 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
899 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
900 case wxAND
: c_rop
= R2_MASKPEN
; break;
901 case wxOR
: c_rop
= R2_MERGEPEN
; break;
902 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
907 c_rop
= R2_COPYPEN
; break;
909 SetROP2((HDC
) dc
, c_rop
);
912 bool wxDC::StartDoc(const wxString
& message
)
914 // We might be previewing, so return TRUE to let it continue.
922 void wxDC::StartPage()
930 // ---------------------------------------------------------------------------
932 // ---------------------------------------------------------------------------
934 long wxDC::GetCharHeight() const
936 TEXTMETRIC lpTextMetric
;
938 GetTextMetrics(GetHdc(), &lpTextMetric
);
940 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
943 long wxDC::GetCharWidth() const
945 TEXTMETRIC lpTextMetric
;
947 GetTextMetrics(GetHdc(), &lpTextMetric
);
949 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
952 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
953 long *descent
, long *externalLeading
,
954 wxFont
*theFont
) const
956 wxFont
*fontToUse
= (wxFont
*) theFont
;
958 fontToUse
= (wxFont
*) &m_font
;
963 GetTextExtentPoint(GetHdc(), (char *)(const char *) string
, strlen((char *)(const char *) string
), &sizeRect
);
964 GetTextMetrics(GetHdc(), &tm
);
966 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
967 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
968 if (descent
) *descent
= tm
.tmDescent
;
969 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
972 void wxDC::SetMapMode(int mode
)
974 m_mappingMode
= mode
;
977 int pixel_height
= 0;
981 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
982 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
983 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
984 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
986 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
991 double mm2pixelsX
= pixel_width
/mm_width
;
992 double mm2pixelsY
= pixel_height
/mm_height
;
998 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
999 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
1004 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
1005 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
1010 m_logicalScaleX
= mm2pixelsX
;
1011 m_logicalScaleY
= mm2pixelsY
;
1016 m_logicalScaleX
= (mm2pixelsX
/10.0);
1017 m_logicalScaleY
= (mm2pixelsY
/10.0);
1023 m_logicalScaleX
= 1.0;
1024 m_logicalScaleY
= 1.0;
1029 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
1030 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
1032 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1033 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1034 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1035 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1036 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1037 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1040 void wxDC::SetUserScale(double x
, double y
)
1045 SetMapMode(m_mappingMode
);
1048 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1050 m_signX
= xLeftRight
? 1 : -1;
1051 m_signY
= yBottomUp
? -1 : 1;
1053 SetMapMode(m_mappingMode
);
1056 void wxDC::SetSystemScale(double x
, double y
)
1061 SetMapMode(m_mappingMode
);
1064 void wxDC::SetLogicalOrigin(long x
, long y
)
1066 m_logicalOriginX
= x
;
1067 m_logicalOriginY
= y
;
1069 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1072 void wxDC::SetDeviceOrigin(long x
, long y
)
1074 m_deviceOriginX
= x
;
1075 m_deviceOriginY
= y
;
1077 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1080 // ---------------------------------------------------------------------------
1081 // coordinates transformations
1082 // ---------------------------------------------------------------------------
1084 long wxDCBase::DeviceToLogicalX(long x
) const
1086 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1089 long wxDCBase::DeviceToLogicalXRel(long x
) const
1091 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1094 long wxDCBase::DeviceToLogicalY(long y
) const
1096 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1099 long wxDCBase::DeviceToLogicalYRel(long y
) const
1101 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1104 long wxDCBase::LogicalToDeviceX(long x
) const
1106 return (long) (floor((x
) - m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1109 long wxDCBase::LogicalToDeviceXRel(long x
) const
1111 return (long) (floor(x
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1114 long wxDCBase::LogicalToDeviceY(long y
) const
1116 return (long) (floor((y
) - m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1119 long wxDCBase::LogicalToDeviceYRel(long y
) const
1121 return (long) (floor(y
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1124 // ---------------------------------------------------------------------------
1126 // ---------------------------------------------------------------------------
1127 bool wxDC::DoBlit(long xdest
, long ydest
, long width
, long height
,
1128 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1130 long xdest1
= xdest
;
1131 long ydest1
= ydest
;
1135 // Chris Breeze 18/5/98: use text foreground/background colours
1136 // when blitting from 1-bit bitmaps
1137 COLORREF old_textground
= ::GetTextColor(GetHdc());
1138 COLORREF old_background
= ::GetBkColor(GetHdc());
1139 if (m_textForegroundColour
.Ok())
1141 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1143 if (m_textBackgroundColour
.Ok())
1145 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1148 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1149 rop
== wxCLEAR
? WHITENESS
:
1150 rop
== wxSET
? BLACKNESS
:
1151 rop
== wxINVERT
? DSTINVERT
:
1152 rop
== wxAND
? MERGECOPY
:
1153 rop
== wxOR
? MERGEPAINT
:
1154 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1155 rop
== wxXOR
? SRCINVERT
:
1156 rop
== wxOR_REVERSE
? MERGEPAINT
:
1157 rop
== wxAND_REVERSE
? SRCERASE
:
1158 rop
== wxSRC_OR
? SRCPAINT
:
1159 rop
== wxSRC_AND
? SRCAND
:
1162 bool success
= TRUE
;
1163 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1167 // Not implemented under Win95 (or maybe a specific device?)
1168 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1169 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1179 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1180 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1181 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1182 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1183 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1184 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1185 ::SelectObject(dc_mask
, 0);
1186 ::DeleteDC(dc_mask
);
1188 // New code from Chris Breeze, 15/7/98
1189 // Blit bitmap with mask
1191 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1193 // If we are printing source colours are screen colours
1194 // not printer colours and so we need copy the bitmap
1197 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1198 HDC dc_src
= (HDC
) source
->m_hDC
;
1200 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1201 for (int x
= 0; x
< width
; x
++)
1203 for (int y
= 0; y
< height
; y
++)
1205 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1208 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1209 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1210 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1211 ::FillRect(GetHdc(), &rect
, brush
);
1212 ::DeleteObject(brush
);
1216 ::SelectObject(dc_mask
, 0);
1217 ::DeleteDC(dc_mask
);
1221 // create a temp buffer bitmap and DCs to access it and the mask
1222 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1223 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1224 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1225 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1226 ::SelectObject(dc_buffer
, buffer_bmap
);
1228 // copy dest to buffer
1229 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1230 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1232 // copy src to buffer using selected raster op
1233 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1234 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1236 // set masked area in buffer to BLACK (pixel value 0)
1237 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1238 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1239 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1240 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1242 // set unmasked area in dest to BLACK
1243 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1244 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1245 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1246 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1247 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1248 ::SetTextColor(GetHdc(), prevCol
);
1250 // OR buffer to dest
1251 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1252 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1254 // tidy up temporary DCs and bitmap
1255 ::SelectObject(dc_mask
, 0);
1256 ::DeleteDC(dc_mask
);
1257 ::SelectObject(dc_buffer
, 0);
1258 ::DeleteDC(dc_buffer
);
1259 ::DeleteObject(buffer_bmap
);
1265 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1267 // If we are printing, source colours are screen colours
1268 // not printer colours and so we need copy the bitmap
1270 HDC dc_src
= (HDC
) source
->m_hDC
;
1272 for (int x
= 0; x
< width
; x
++)
1274 for (int y
= 0; y
< height
; y
++)
1276 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1277 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1278 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1279 ::FillRect(GetHdc(), &rect
, brush
);
1280 ::DeleteObject(brush
);
1286 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1287 xsrc1
, ysrc1
, dwRop
) != 0);
1290 ::SetTextColor(GetHdc(), old_textground
);
1291 ::SetBkColor(GetHdc(), old_background
);
1296 void wxDC::DoGetSize(int *w
, int *h
) const
1298 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1299 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1302 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1304 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1305 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1308 wxSize
wxDC::GetPPI() const
1310 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1311 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1313 return wxSize(x
, y
);
1316 // For use by wxWindows only, unless custom units are required.
1317 void wxDC::SetLogicalScale(double x
, double y
)
1319 m_logicalScaleX
= x
;
1320 m_logicalScaleY
= y
;
1323 #if WXWIN_COMPATIBILITY
1324 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1325 float *descent
, float *externalLeading
,
1326 wxFont
*theFont
, bool use16bit
) const
1328 long x1
, y1
, descent1
, externalLeading1
;
1329 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1332 *descent
= descent1
;
1333 if (externalLeading
)
1334 *externalLeading
= externalLeading1
;
1338 // ---------------------------------------------------------------------------
1339 // spline drawing code
1340 // ---------------------------------------------------------------------------
1344 class wxSpline
: public wxObject
1350 wxSpline(wxList
*list
);
1351 void DeletePoints();
1353 // Doesn't delete points
1357 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1359 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1360 double a3
, double b3
, double a4
, double b4
);
1361 void wx_clear_stack();
1362 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1363 double *y3
, double *x4
, double *y4
);
1364 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1365 double x4
, double y4
);
1366 static bool wx_spline_add_point(double x
, double y
);
1367 static void wx_spline_draw_point_array(wxDC
*dc
);
1368 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1370 void wxDC::DoDrawSpline(wxList
*list
)
1372 wxSpline
spline(list
);
1374 wx_draw_open_spline(this, &spline
);
1377 wxList wx_spline_point_list
;
1379 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1382 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1383 double x1
, y1
, x2
, y2
;
1385 wxNode
*node
= spline
->points
->First();
1386 p
= (wxPoint
*)node
->Data();
1391 node
= node
->Next();
1392 p
= (wxPoint
*)node
->Data();
1396 cx1
= (double)((x1
+ x2
) / 2);
1397 cy1
= (double)((y1
+ y2
) / 2);
1398 cx2
= (double)((cx1
+ x2
) / 2);
1399 cy2
= (double)((cy1
+ y2
) / 2);
1401 wx_spline_add_point(x1
, y1
);
1403 while ((node
= node
->Next()) != NULL
)
1405 p
= (wxPoint
*)node
->Data();
1410 cx4
= (double)(x1
+ x2
) / 2;
1411 cy4
= (double)(y1
+ y2
) / 2;
1412 cx3
= (double)(x1
+ cx4
) / 2;
1413 cy3
= (double)(y1
+ cy4
) / 2;
1415 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1419 cx2
= (double)(cx1
+ x2
) / 2;
1420 cy2
= (double)(cy1
+ y2
) / 2;
1423 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1424 wx_spline_add_point(x2
, y2
);
1426 wx_spline_draw_point_array(dc
);
1430 /********************* CURVES FOR SPLINES *****************************
1432 The following spline drawing routine is from
1434 "An Algorithm for High-Speed Curve Generation"
1435 by George Merrill Chaikin,
1436 Computer Graphics and Image Processing, 3, Academic Press,
1441 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1442 Computer Graphics and Image Processing, 4, Academic Press,
1445 ***********************************************************************/
1447 #define half(z1, z2) ((z1+z2)/2.0)
1450 /* iterative version */
1452 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1455 register double xmid
, ymid
;
1456 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1459 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1461 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1462 xmid
= (double)half(x2
, x3
);
1463 ymid
= (double)half(y2
, y3
);
1464 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1465 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1466 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1467 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1469 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1470 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1471 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1472 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1478 /* utilities used by spline drawing routines */
1481 typedef struct wx_spline_stack_struct
{
1482 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1486 #define SPLINE_STACK_DEPTH 20
1487 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1488 static Stack
*wx_stack_top
;
1489 static int wx_stack_count
;
1491 void wx_clear_stack()
1493 wx_stack_top
= wx_spline_stack
;
1497 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1499 wx_stack_top
->x1
= x1
;
1500 wx_stack_top
->y1
= y1
;
1501 wx_stack_top
->x2
= x2
;
1502 wx_stack_top
->y2
= y2
;
1503 wx_stack_top
->x3
= x3
;
1504 wx_stack_top
->y3
= y3
;
1505 wx_stack_top
->x4
= x4
;
1506 wx_stack_top
->y4
= y4
;
1511 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1512 double *x3
, double *y3
, double *x4
, double *y4
)
1514 if (wx_stack_count
== 0)
1518 *x1
= wx_stack_top
->x1
;
1519 *y1
= wx_stack_top
->y1
;
1520 *x2
= wx_stack_top
->x2
;
1521 *y2
= wx_stack_top
->y2
;
1522 *x3
= wx_stack_top
->x3
;
1523 *y3
= wx_stack_top
->y3
;
1524 *x4
= wx_stack_top
->x4
;
1525 *y4
= wx_stack_top
->y4
;
1529 static bool wx_spline_add_point(double x
, double y
)
1531 wxPoint
*point
= new wxPoint
;
1534 wx_spline_point_list
.Append((wxObject
*)point
);
1538 static void wx_spline_draw_point_array(wxDC
*dc
)
1540 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1541 wxNode
*node
= wx_spline_point_list
.First();
1544 wxPoint
*point
= (wxPoint
*)node
->Data();
1547 node
= wx_spline_point_list
.First();
1551 wxSpline::wxSpline(wxList
*list
)
1556 wxSpline::~wxSpline()
1560 void wxSpline::DeletePoints()
1562 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1564 wxPoint
*point
= (wxPoint
*)node
->Data();
1572 #endif // wxUSE_SPLINES