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 // ---------------------------------------------------------------------------
300 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
304 wxCHECK_RET( m_selectedBitmap
.Ok(), _T("this DC can't be cleared") );
306 rect
.left
= 0; rect
.top
= 0;
307 rect
.right
= m_selectedBitmap
.GetWidth();
308 rect
.bottom
= m_selectedBitmap
.GetHeight();
311 (void) ::SetMapMode(GetHdc(), MM_TEXT
);
313 DWORD colour
= GetBkColor(GetHdc());
314 HBRUSH brush
= CreateSolidBrush(colour
);
315 FillRect(GetHdc(), &rect
, brush
);
318 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
319 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
320 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
321 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
322 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
325 void wxDC::DoFloodFill(long x
, long y
, const wxColour
& col
, int style
)
327 (void)ExtFloodFill(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
329 style
== wxFLOOD_SURFACE
? FLOODFILLSURFACE
332 CalcBoundingBox(x
, y
);
335 bool wxDC::DoGetPixel(long x
, long y
, wxColour
*col
) const
337 // added by steve 29.12.94 (copied from DrawPoint)
338 // returns TRUE for pixels in the color of the current pen
339 // and FALSE for all other pixels colors
340 // if col is non-NULL return the color of the pixel
342 // get the color of the pixel
343 COLORREF pixelcolor
= ::GetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
));
344 // get the color of the pen
345 COLORREF pencolor
= 0x00ffffff;
348 pencolor
= m_pen
.GetColour().GetPixel();
351 // return the color of the pixel
353 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
355 // check, if color of the pixels is the same as the color
356 // of the current pen
357 return(pixelcolor
==pencolor
);
360 void wxDC::DoCrossHair(long x
, long y
)
362 long x1
= x
-VIEWPORT_EXTENT
;
363 long y1
= y
-VIEWPORT_EXTENT
;
364 long x2
= x
+VIEWPORT_EXTENT
;
365 long y2
= y
+VIEWPORT_EXTENT
;
367 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
368 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y
));
370 (void)MoveToEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
371 (void)LineTo(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y2
));
373 CalcBoundingBox(x1
, y1
);
374 CalcBoundingBox(x2
, y2
);
377 void wxDC::DoDrawLine(long x1
, long y1
, long x2
, long y2
)
379 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
380 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y2
));
382 /* MATTHEW: [6] New normalization */
383 #if WX_STANDARD_GRAPHICS
384 (void)LineTo(GetHdc(), XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
387 CalcBoundingBox(x1
, y1
);
388 CalcBoundingBox(x2
, y2
);
391 void wxDC::DoDrawArc(long x1
,long y1
,long x2
,long y2
, long xc
, long yc
)
395 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
396 if (x1
==x2
&& x2
==y2
)
398 DrawEllipse(xc
,yc
,(long)(radius
*2.0),(long)(radius
*2.0));
402 long xx1
= XLOG2DEV(x1
);
403 long yy1
= YLOG2DEV(y1
);
404 long xx2
= XLOG2DEV(x2
);
405 long yy2
= YLOG2DEV(y2
);
406 long xxc
= XLOG2DEV(xc
);
407 long yyc
= YLOG2DEV(yc
);
408 long ray
= (long) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
)));
410 (void)MoveToEx(GetHdc(), (int) xx1
, (int) yy1
, NULL
);
411 long xxx1
= (long) (xxc
-ray
);
412 long yyy1
= (long) (yyc
-ray
);
413 long xxx2
= (long) (xxc
+ray
);
414 long yyy2
= (long) (yyc
+ray
);
415 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
417 // Have to add 1 to bottom-right corner of rectangle
418 // to make semi-circles look right (crooked line otherwise).
419 // Unfortunately this is not a reliable method, depends
420 // on the size of shape.
421 // TODO: figure out why this happens!
422 Pie(GetHdc(),xxx1
,yyy1
,xxx2
+1,yyy2
+1,
426 Arc(GetHdc(),xxx1
,yyy1
,xxx2
,yyy2
,
429 CalcBoundingBox((xc
-radius
), (yc
-radius
));
430 CalcBoundingBox((xc
+radius
), (yc
+radius
));
433 void wxDC::DoDrawPoint(long x
, long y
)
435 COLORREF color
= 0x00ffffff;
438 color
= m_pen
.GetColour().GetPixel();
441 SetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), color
);
443 CalcBoundingBox(x
, y
);
446 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], long xoffset
, long yoffset
,int fillStyle
)
448 // Do things less efficiently if we have offsets
449 if (xoffset
!= 0 || yoffset
!= 0)
451 POINT
*cpoints
= new POINT
[n
];
453 for (i
= 0; i
< n
; i
++)
455 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
456 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
458 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
460 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
461 (void)Polygon(GetHdc(), cpoints
, n
);
462 SetPolyFillMode(GetHdc(),prev
);
468 for (i
= 0; i
< n
; i
++)
469 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
471 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
472 (void)Polygon(GetHdc(), (POINT
*) points
, n
);
473 SetPolyFillMode(GetHdc(),prev
);
477 void wxDC::DoDrawLines(int n
, wxPoint points
[], long xoffset
, long yoffset
)
479 // Do things less efficiently if we have offsets
480 if (xoffset
!= 0 || yoffset
!= 0)
482 POINT
*cpoints
= new POINT
[n
];
484 for (i
= 0; i
< n
; i
++)
486 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
487 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
489 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
491 (void)Polyline(GetHdc(), cpoints
, n
);
497 for (i
= 0; i
< n
; i
++)
498 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
500 (void)Polyline(GetHdc(), (POINT
*) points
, n
);
504 void wxDC::DoDrawRectangle(long x
, long y
, long width
, long height
)
507 long y2
= y
+ height
;
509 /* MATTHEW: [6] new normalization */
510 #if WX_STANDARD_GRAPHICS
511 bool do_brush
, do_pen
;
513 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
514 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
517 HPEN orig_pen
= NULL
;
519 if (do_pen
|| !m_pen
.Ok())
520 orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
522 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
523 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
525 if (do_pen
|| !m_pen
.Ok())
526 ::SelectObject(GetHdc() , orig_pen
);
529 HBRUSH orig_brush
= NULL
;
531 if (do_brush
|| !m_brush
.Ok())
532 orig_brush
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
534 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
535 XLOG2DEV(x2
), YLOG2DEV(y2
));
537 if (do_brush
|| !m_brush
.Ok())
538 ::SelectObject(GetHdc(), orig_brush
);
541 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
544 CalcBoundingBox(x
, y
);
545 CalcBoundingBox(x2
, y2
);
548 void wxDC::DoDrawRoundedRectangle(long x
, long y
, long width
, long height
, double radius
)
550 // Now, a negative radius value is interpreted to mean
551 // 'the proportion of the smallest X or Y dimension'
555 double smallest
= 0.0;
560 radius
= (- radius
* smallest
);
564 long y2
= (y
+height
);
566 (void)RoundRect(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
567 YLOG2DEV(y2
), (int) (2*XLOG2DEV(radius
)), (int)( 2*YLOG2DEV(radius
)));
569 CalcBoundingBox(x
, y
);
570 CalcBoundingBox(x2
, y2
);
573 void wxDC::DoDrawEllipse(long x
, long y
, long width
, long height
)
576 long y2
= (y
+height
);
578 (void)Ellipse(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
580 CalcBoundingBox(x
, y
);
581 CalcBoundingBox(x2
, y2
);
584 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
585 void wxDC::DoDrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
)
590 const double deg2rad
= 3.14159265359 / 180.0;
591 int rx1
= XLOG2DEV(x
+w
/2);
592 int ry1
= YLOG2DEV(y
+h
/2);
595 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
596 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
597 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
598 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
600 // draw pie with NULL_PEN first and then outline otherwise a line is
601 // drawn from the start and end points to the centre
602 HPEN orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
605 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
610 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
611 rx1
, ry1
-1, rx2
, ry2
-1);
613 ::SelectObject(GetHdc(), orig_pen
);
614 (void)Arc(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
617 CalcBoundingBox(x
, y
);
618 CalcBoundingBox(x2
, y2
);
621 void wxDC::DoDrawIcon(const wxIcon
& icon
, long x
, long y
)
623 #if defined(__WIN32__) && !defined(__SC__) && !defined(__TWIN32__)
624 ::DrawIconEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON(),
625 icon
.GetWidth(), icon
.GetHeight(), 0, 0, DI_NORMAL
);
627 ::DrawIcon(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
630 CalcBoundingBox(x
, y
);
631 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
634 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, long x
, long y
, bool useMask
)
639 // If we're not drawing transparently, and not drawing to a printer,
640 // optimize this function to use Windows functions.
641 if (!useMask
&& !IsKindOf(CLASSINFO(wxPrinterDC
)))
644 HDC memdc
= ::CreateCompatibleDC( cdc
);
645 HBITMAP hbitmap
= (HBITMAP
) bmp
.GetHBITMAP( );
646 ::SelectObject( memdc
, hbitmap
);
647 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
652 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
654 memDC
.SelectObject(bmp
);
656 /* Not sure if we need this. The mask should leave the
657 * masked areas as per the original background of this DC.
660 // There might be transparent areas, so make these
661 // the same colour as this DC
662 memDC.SetBackground(* GetBackground());
666 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
668 memDC
.SelectObject(wxNullBitmap
);
672 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
674 if (m_textForegroundColour
.Ok())
675 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
677 DWORD old_background
= 0;
678 if (m_textBackgroundColour
.Ok())
680 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
683 if (m_backgroundMode
== wxTRANSPARENT
)
684 SetBkMode(GetHdc(), TRANSPARENT
);
686 SetBkMode(GetHdc(), OPAQUE
);
688 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), WXSTRINGCAST text
, wxStrlen(WXSTRINGCAST text
));
690 if (m_textBackgroundColour
.Ok())
691 (void)SetBkColor(GetHdc(), old_background
);
693 CalcBoundingBox(x
, y
);
696 GetTextExtent(text
, &w
, &h
);
697 CalcBoundingBox((x
+ w
), (y
+ h
));
700 // ---------------------------------------------------------------------------
702 // ---------------------------------------------------------------------------
704 void wxDC::SetPalette(const wxPalette
& palette
)
706 // Set the old object temporarily, in case the assignment deletes an object
707 // that's not yet selected out.
710 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
718 // Setting a NULL colourmap is a way of restoring
719 // the original colourmap
722 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
729 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
731 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
733 m_oldPalette
= (WXHPALETTE
) oldPal
;
735 ::RealizePalette(GetHdc());
739 void wxDC::SetFont(const wxFont
& the_font
)
741 // Set the old object temporarily, in case the assignment deletes an object
742 // that's not yet selected out.
745 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
754 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
758 if (m_font
.Ok() && m_font
.GetResourceHandle())
760 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
761 if (f
== (HFONT
) NULL
)
763 wxLogDebug(_T("::SelectObject failed in wxDC::SetFont."));
766 m_oldFont
= (WXHFONT
) f
;
770 void wxDC::SetPen(const wxPen
& pen
)
772 // Set the old object temporarily, in case the assignment deletes an object
773 // that's not yet selected out.
776 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
785 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
791 if (m_pen
.GetResourceHandle())
793 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
795 m_oldPen
= (WXHPEN
) p
;
800 void wxDC::SetBrush(const wxBrush
& brush
)
802 // Set the old object temporarily, in case the assignment deletes an object
803 // that's not yet selected out.
806 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
815 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
821 if (m_brush
.GetResourceHandle())
824 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
826 m_oldBrush
= (WXHBRUSH
) b
;
831 void wxDC::SetBackground(const wxBrush
& brush
)
833 m_backgroundBrush
= brush
;
835 if (!m_backgroundBrush
.Ok())
840 bool customColours
= TRUE
;
841 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
842 // change background colours from the control-panel specified colours.
843 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
844 customColours
= FALSE
;
848 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
850 m_canvas
->SetTransparent(TRUE
);
854 // New behaviour, 10/2/99: setting the background brush of a DC
855 // doesn't affect the window background colour. However,
856 // I'm leaving in the transparency setting because it's needed by
857 // various controls (e.g. wxStaticText) to determine whether to draw
858 // transparently or not. TODO: maybe this should be a new function
859 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
861 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
862 m_canvas
->SetTransparent(FALSE
);
866 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
868 (void)SetBkColor(GetHdc(), new_color
);
872 void wxDC::SetBackgroundMode(int mode
)
874 m_backgroundMode
= mode
;
876 if (m_backgroundMode
== wxTRANSPARENT
)
877 ::SetBkMode(GetHdc(), TRANSPARENT
);
879 ::SetBkMode(GetHdc(), OPAQUE
);
882 void wxDC::SetLogicalFunction(int function
)
884 m_logicalFunction
= function
;
886 SetRop((WXHDC
) m_hDC
);
889 void wxDC::SetRop(WXHDC dc
)
891 if (!dc
|| m_logicalFunction
< 0)
895 // These may be wrong
896 switch (m_logicalFunction
)
898 // case wxXOR: c_rop = R2_XORPEN; break;
899 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
900 case wxINVERT
: c_rop
= R2_NOT
; break;
901 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
902 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
903 case wxCLEAR
: c_rop
= R2_WHITE
; break;
904 case wxSET
: c_rop
= R2_BLACK
; break;
905 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
906 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
907 case wxAND
: c_rop
= R2_MASKPEN
; break;
908 case wxOR
: c_rop
= R2_MERGEPEN
; break;
909 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
914 c_rop
= R2_COPYPEN
; break;
916 SetROP2((HDC
) dc
, c_rop
);
919 bool wxDC::StartDoc(const wxString
& message
)
921 // We might be previewing, so return TRUE to let it continue.
929 void wxDC::StartPage()
937 // ---------------------------------------------------------------------------
939 // ---------------------------------------------------------------------------
941 long wxDC::GetCharHeight() const
943 TEXTMETRIC lpTextMetric
;
945 GetTextMetrics(GetHdc(), &lpTextMetric
);
947 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
950 long wxDC::GetCharWidth() const
952 TEXTMETRIC lpTextMetric
;
954 GetTextMetrics(GetHdc(), &lpTextMetric
);
956 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
959 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
960 long *descent
, long *externalLeading
,
961 wxFont
*theFont
) const
963 wxFont
*fontToUse
= (wxFont
*) theFont
;
965 fontToUse
= (wxFont
*) &m_font
;
970 GetTextExtentPoint(GetHdc(), WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
971 GetTextMetrics(GetHdc(), &tm
);
973 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
974 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
975 if (descent
) *descent
= tm
.tmDescent
;
976 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
979 void wxDC::SetMapMode(int mode
)
981 m_mappingMode
= mode
;
984 int pixel_height
= 0;
988 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
989 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
990 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
991 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
993 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
998 double mm2pixelsX
= pixel_width
/mm_width
;
999 double mm2pixelsY
= pixel_height
/mm_height
;
1005 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
1006 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
1011 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
1012 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
1017 m_logicalScaleX
= mm2pixelsX
;
1018 m_logicalScaleY
= mm2pixelsY
;
1023 m_logicalScaleX
= (mm2pixelsX
/10.0);
1024 m_logicalScaleY
= (mm2pixelsY
/10.0);
1030 m_logicalScaleX
= 1.0;
1031 m_logicalScaleY
= 1.0;
1036 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
1037 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
1039 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1040 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1041 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1042 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1043 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1044 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1047 void wxDC::SetUserScale(double x
, double y
)
1052 SetMapMode(m_mappingMode
);
1055 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1057 m_signX
= xLeftRight
? 1 : -1;
1058 m_signY
= yBottomUp
? -1 : 1;
1060 SetMapMode(m_mappingMode
);
1063 void wxDC::SetSystemScale(double x
, double y
)
1068 SetMapMode(m_mappingMode
);
1071 void wxDC::SetLogicalOrigin(long x
, long y
)
1073 m_logicalOriginX
= x
;
1074 m_logicalOriginY
= y
;
1076 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1079 void wxDC::SetDeviceOrigin(long x
, long y
)
1081 m_deviceOriginX
= x
;
1082 m_deviceOriginY
= y
;
1084 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1087 // ---------------------------------------------------------------------------
1088 // coordinates transformations
1089 // ---------------------------------------------------------------------------
1091 long wxDCBase::DeviceToLogicalX(long x
) const
1093 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1096 long wxDCBase::DeviceToLogicalXRel(long x
) const
1098 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1101 long wxDCBase::DeviceToLogicalY(long y
) const
1103 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1106 long wxDCBase::DeviceToLogicalYRel(long y
) const
1108 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1111 long wxDCBase::LogicalToDeviceX(long x
) const
1113 return (long) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1116 long wxDCBase::LogicalToDeviceXRel(long x
) const
1118 return (long) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1121 long wxDCBase::LogicalToDeviceY(long y
) const
1123 return (long) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1126 long wxDCBase::LogicalToDeviceYRel(long y
) const
1128 return (long) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1131 // ---------------------------------------------------------------------------
1133 // ---------------------------------------------------------------------------
1134 bool wxDC::DoBlit(long xdest
, long ydest
, long width
, long height
,
1135 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1137 long xdest1
= xdest
;
1138 long ydest1
= ydest
;
1142 // Chris Breeze 18/5/98: use text foreground/background colours
1143 // when blitting from 1-bit bitmaps
1144 COLORREF old_textground
= ::GetTextColor(GetHdc());
1145 COLORREF old_background
= ::GetBkColor(GetHdc());
1146 if (m_textForegroundColour
.Ok())
1148 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1150 if (m_textBackgroundColour
.Ok())
1152 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1155 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1156 rop
== wxCLEAR
? WHITENESS
:
1157 rop
== wxSET
? BLACKNESS
:
1158 rop
== wxINVERT
? DSTINVERT
:
1159 rop
== wxAND
? MERGECOPY
:
1160 rop
== wxOR
? MERGEPAINT
:
1161 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1162 rop
== wxXOR
? SRCINVERT
:
1163 rop
== wxOR_REVERSE
? MERGEPAINT
:
1164 rop
== wxAND_REVERSE
? SRCERASE
:
1165 rop
== wxSRC_OR
? SRCPAINT
:
1166 rop
== wxSRC_AND
? SRCAND
:
1169 bool success
= TRUE
;
1170 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1174 // Not implemented under Win95 (or maybe a specific device?)
1175 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1176 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1186 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1187 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1188 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1189 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1190 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1191 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1192 ::SelectObject(dc_mask
, 0);
1193 ::DeleteDC(dc_mask
);
1195 // New code from Chris Breeze, 15/7/98
1196 // Blit bitmap with mask
1198 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1200 // If we are printing source colours are screen colours
1201 // not printer colours and so we need copy the bitmap
1204 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1205 HDC dc_src
= (HDC
) source
->m_hDC
;
1207 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1208 for (int x
= 0; x
< width
; x
++)
1210 for (int y
= 0; y
< height
; y
++)
1212 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1215 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1216 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1217 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1218 ::FillRect(GetHdc(), &rect
, brush
);
1219 ::DeleteObject(brush
);
1223 ::SelectObject(dc_mask
, 0);
1224 ::DeleteDC(dc_mask
);
1228 // create a temp buffer bitmap and DCs to access it and the mask
1229 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1230 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1231 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1232 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1233 ::SelectObject(dc_buffer
, buffer_bmap
);
1235 // copy dest to buffer
1236 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1237 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1239 // copy src to buffer using selected raster op
1240 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1241 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1243 // set masked area in buffer to BLACK (pixel value 0)
1244 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1245 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1246 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1247 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1249 // set unmasked area in dest to BLACK
1250 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1251 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1252 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1253 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1254 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1255 ::SetTextColor(GetHdc(), prevCol
);
1257 // OR buffer to dest
1258 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1259 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1261 // tidy up temporary DCs and bitmap
1262 ::SelectObject(dc_mask
, 0);
1263 ::DeleteDC(dc_mask
);
1264 ::SelectObject(dc_buffer
, 0);
1265 ::DeleteDC(dc_buffer
);
1266 ::DeleteObject(buffer_bmap
);
1272 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1274 // If we are printing, source colours are screen colours
1275 // not printer colours and so we need copy the bitmap
1277 HDC dc_src
= (HDC
) source
->m_hDC
;
1279 for (int x
= 0; x
< width
; x
++)
1281 for (int y
= 0; y
< height
; y
++)
1283 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1284 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1285 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1286 ::FillRect(GetHdc(), &rect
, brush
);
1287 ::DeleteObject(brush
);
1293 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1294 xsrc1
, ysrc1
, dwRop
) != 0);
1297 ::SetTextColor(GetHdc(), old_textground
);
1298 ::SetBkColor(GetHdc(), old_background
);
1303 void wxDC::DoGetSize(int *w
, int *h
) const
1305 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1306 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1309 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1311 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1312 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1315 wxSize
wxDC::GetPPI() const
1317 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1318 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1320 return wxSize(x
, y
);
1323 // For use by wxWindows only, unless custom units are required.
1324 void wxDC::SetLogicalScale(double x
, double y
)
1326 m_logicalScaleX
= x
;
1327 m_logicalScaleY
= y
;
1330 #if WXWIN_COMPATIBILITY
1331 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1332 float *descent
, float *externalLeading
,
1333 wxFont
*theFont
, bool use16bit
) const
1335 long x1
, y1
, descent1
, externalLeading1
;
1336 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1339 *descent
= descent1
;
1340 if (externalLeading
)
1341 *externalLeading
= externalLeading1
;
1345 // ---------------------------------------------------------------------------
1346 // spline drawing code
1347 // ---------------------------------------------------------------------------
1351 class wxSpline
: public wxObject
1357 wxSpline(wxList
*list
);
1358 void DeletePoints();
1360 // Doesn't delete points
1364 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1366 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1367 double a3
, double b3
, double a4
, double b4
);
1368 void wx_clear_stack();
1369 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1370 double *y3
, double *x4
, double *y4
);
1371 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1372 double x4
, double y4
);
1373 static bool wx_spline_add_point(double x
, double y
);
1374 static void wx_spline_draw_point_array(wxDC
*dc
);
1375 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1377 void wxDC::DoDrawSpline(wxList
*list
)
1379 wxSpline
spline(list
);
1381 wx_draw_open_spline(this, &spline
);
1384 wxList wx_spline_point_list
;
1386 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1389 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1390 double x1
, y1
, x2
, y2
;
1392 wxNode
*node
= spline
->points
->First();
1393 p
= (wxPoint
*)node
->Data();
1398 node
= node
->Next();
1399 p
= (wxPoint
*)node
->Data();
1403 cx1
= (double)((x1
+ x2
) / 2);
1404 cy1
= (double)((y1
+ y2
) / 2);
1405 cx2
= (double)((cx1
+ x2
) / 2);
1406 cy2
= (double)((cy1
+ y2
) / 2);
1408 wx_spline_add_point(x1
, y1
);
1410 while ((node
= node
->Next()) != NULL
)
1412 p
= (wxPoint
*)node
->Data();
1417 cx4
= (double)(x1
+ x2
) / 2;
1418 cy4
= (double)(y1
+ y2
) / 2;
1419 cx3
= (double)(x1
+ cx4
) / 2;
1420 cy3
= (double)(y1
+ cy4
) / 2;
1422 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1426 cx2
= (double)(cx1
+ x2
) / 2;
1427 cy2
= (double)(cy1
+ y2
) / 2;
1430 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1431 wx_spline_add_point(x2
, y2
);
1433 wx_spline_draw_point_array(dc
);
1437 /********************* CURVES FOR SPLINES *****************************
1439 The following spline drawing routine is from
1441 "An Algorithm for High-Speed Curve Generation"
1442 by George Merrill Chaikin,
1443 Computer Graphics and Image Processing, 3, Academic Press,
1448 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1449 Computer Graphics and Image Processing, 4, Academic Press,
1452 ***********************************************************************/
1454 #define half(z1, z2) ((z1+z2)/2.0)
1457 /* iterative version */
1459 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1462 register double xmid
, ymid
;
1463 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1466 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1468 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1469 xmid
= (double)half(x2
, x3
);
1470 ymid
= (double)half(y2
, y3
);
1471 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1472 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1473 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1474 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1476 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1477 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1478 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1479 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1485 /* utilities used by spline drawing routines */
1488 typedef struct wx_spline_stack_struct
{
1489 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1493 #define SPLINE_STACK_DEPTH 20
1494 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1495 static Stack
*wx_stack_top
;
1496 static int wx_stack_count
;
1498 void wx_clear_stack()
1500 wx_stack_top
= wx_spline_stack
;
1504 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1506 wx_stack_top
->x1
= x1
;
1507 wx_stack_top
->y1
= y1
;
1508 wx_stack_top
->x2
= x2
;
1509 wx_stack_top
->y2
= y2
;
1510 wx_stack_top
->x3
= x3
;
1511 wx_stack_top
->y3
= y3
;
1512 wx_stack_top
->x4
= x4
;
1513 wx_stack_top
->y4
= y4
;
1518 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1519 double *x3
, double *y3
, double *x4
, double *y4
)
1521 if (wx_stack_count
== 0)
1525 *x1
= wx_stack_top
->x1
;
1526 *y1
= wx_stack_top
->y1
;
1527 *x2
= wx_stack_top
->x2
;
1528 *y2
= wx_stack_top
->y2
;
1529 *x3
= wx_stack_top
->x3
;
1530 *y3
= wx_stack_top
->y3
;
1531 *x4
= wx_stack_top
->x4
;
1532 *y4
= wx_stack_top
->y4
;
1536 static bool wx_spline_add_point(double x
, double y
)
1538 wxPoint
*point
= new wxPoint
;
1541 wx_spline_point_list
.Append((wxObject
*)point
);
1545 static void wx_spline_draw_point_array(wxDC
*dc
)
1547 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1548 wxNode
*node
= wx_spline_point_list
.First();
1551 wxPoint
*point
= (wxPoint
*)node
->Data();
1554 node
= wx_spline_point_list
.First();
1558 wxSpline::wxSpline(wxList
*list
)
1563 wxSpline::~wxSpline()
1567 void wxSpline::DeletePoints()
1569 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1571 wxPoint
*point
= (wxPoint
*)node
->Data();
1579 #endif // wxUSE_SPLINES