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
);
646 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
648 memDC
.SelectObject(bmp
);
650 /* Not sure if we need this. The mask should leave the
651 * masked areas as per the original background of this DC.
654 // There might be transparent areas, so make these
655 // the same colour as this DC
656 memDC.SetBackground(* GetBackground());
660 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
662 memDC
.SelectObject(wxNullBitmap
);
666 void wxDC::DoDrawText(const wxString
& text
, long x
, long y
)
668 if (m_textForegroundColour
.Ok())
669 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
671 DWORD old_background
= 0;
672 if (m_textBackgroundColour
.Ok())
674 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
677 if (m_backgroundMode
== wxTRANSPARENT
)
678 SetBkMode(GetHdc(), TRANSPARENT
);
680 SetBkMode(GetHdc(), OPAQUE
);
682 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (char *) (const char *)text
, strlen((const char *)text
));
684 if (m_textBackgroundColour
.Ok())
685 (void)SetBkColor(GetHdc(), old_background
);
687 CalcBoundingBox(x
, y
);
690 GetTextExtent(text
, &w
, &h
);
691 CalcBoundingBox((x
+ w
), (y
+ h
));
694 // ---------------------------------------------------------------------------
696 // ---------------------------------------------------------------------------
698 void wxDC::SetPalette(const wxPalette
& palette
)
700 // Set the old object temporarily, in case the assignment deletes an object
701 // that's not yet selected out.
704 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
712 // Setting a NULL colourmap is a way of restoring
713 // the original colourmap
716 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
723 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
725 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
727 m_oldPalette
= (WXHPALETTE
) oldPal
;
729 ::RealizePalette(GetHdc());
733 void wxDC::SetFont(const wxFont
& the_font
)
735 // Set the old object temporarily, in case the assignment deletes an object
736 // that's not yet selected out.
739 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
748 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
752 if (m_font
.Ok() && m_font
.GetResourceHandle())
754 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
755 if (f
== (HFONT
) NULL
)
757 wxLogDebug("::SelectObject failed in wxDC::SetFont.");
760 m_oldFont
= (WXHFONT
) f
;
764 void wxDC::SetPen(const wxPen
& pen
)
766 // Set the old object temporarily, in case the assignment deletes an object
767 // that's not yet selected out.
770 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
779 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
785 if (m_pen
.GetResourceHandle())
787 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
789 m_oldPen
= (WXHPEN
) p
;
794 void wxDC::SetBrush(const wxBrush
& brush
)
796 // Set the old object temporarily, in case the assignment deletes an object
797 // that's not yet selected out.
800 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
809 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
815 if (m_brush
.GetResourceHandle())
818 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
820 m_oldBrush
= (WXHBRUSH
) b
;
825 void wxDC::SetBackground(const wxBrush
& brush
)
827 m_backgroundBrush
= brush
;
829 if (!m_backgroundBrush
.Ok())
834 bool customColours
= TRUE
;
835 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
836 // change background colours from the control-panel specified colours.
837 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
838 customColours
= FALSE
;
842 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
844 m_canvas
->SetTransparent(TRUE
);
848 // New behaviour, 10/2/99: setting the background brush of a DC
849 // doesn't affect the window background colour. However,
850 // I'm leaving in the transparency setting because it's needed by
851 // various controls (e.g. wxStaticText) to determine whether to draw
852 // transparently or not. TODO: maybe this should be a new function
853 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
855 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
856 m_canvas
->SetTransparent(FALSE
);
860 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
862 (void)SetBkColor(GetHdc(), new_color
);
866 void wxDC::SetBackgroundMode(int mode
)
868 m_backgroundMode
= mode
;
870 if (m_backgroundMode
== wxTRANSPARENT
)
871 ::SetBkMode(GetHdc(), TRANSPARENT
);
873 ::SetBkMode(GetHdc(), OPAQUE
);
876 void wxDC::SetLogicalFunction(int function
)
878 m_logicalFunction
= function
;
880 SetRop((WXHDC
) m_hDC
);
883 void wxDC::SetRop(WXHDC dc
)
885 if (!dc
|| m_logicalFunction
< 0)
889 // These may be wrong
890 switch (m_logicalFunction
)
892 // case wxXOR: c_rop = R2_XORPEN; break;
893 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
894 case wxINVERT
: c_rop
= R2_NOT
; break;
895 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
896 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
897 case wxCLEAR
: c_rop
= R2_WHITE
; break;
898 case wxSET
: c_rop
= R2_BLACK
; break;
899 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
900 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
901 case wxAND
: c_rop
= R2_MASKPEN
; break;
902 case wxOR
: c_rop
= R2_MERGEPEN
; break;
903 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
908 c_rop
= R2_COPYPEN
; break;
910 SetROP2((HDC
) dc
, c_rop
);
913 bool wxDC::StartDoc(const wxString
& message
)
915 // We might be previewing, so return TRUE to let it continue.
923 void wxDC::StartPage()
931 // ---------------------------------------------------------------------------
933 // ---------------------------------------------------------------------------
935 long wxDC::GetCharHeight() const
937 TEXTMETRIC lpTextMetric
;
939 GetTextMetrics(GetHdc(), &lpTextMetric
);
941 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
944 long wxDC::GetCharWidth() const
946 TEXTMETRIC lpTextMetric
;
948 GetTextMetrics(GetHdc(), &lpTextMetric
);
950 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
953 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
954 long *descent
, long *externalLeading
,
955 wxFont
*theFont
) const
957 wxFont
*fontToUse
= (wxFont
*) theFont
;
959 fontToUse
= (wxFont
*) &m_font
;
964 GetTextExtentPoint(GetHdc(), (char *)(const char *) string
, strlen((char *)(const char *) string
), &sizeRect
);
965 GetTextMetrics(GetHdc(), &tm
);
967 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
968 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
969 if (descent
) *descent
= tm
.tmDescent
;
970 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
973 void wxDC::SetMapMode(int mode
)
975 m_mappingMode
= mode
;
978 int pixel_height
= 0;
982 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
983 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
984 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
985 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
987 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
992 double mm2pixelsX
= pixel_width
/mm_width
;
993 double mm2pixelsY
= pixel_height
/mm_height
;
999 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
1000 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
1005 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
1006 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
1011 m_logicalScaleX
= mm2pixelsX
;
1012 m_logicalScaleY
= mm2pixelsY
;
1017 m_logicalScaleX
= (mm2pixelsX
/10.0);
1018 m_logicalScaleY
= (mm2pixelsY
/10.0);
1024 m_logicalScaleX
= 1.0;
1025 m_logicalScaleY
= 1.0;
1030 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
1031 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
1033 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1034 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1035 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1036 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1037 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1038 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1041 void wxDC::SetUserScale(double x
, double y
)
1046 SetMapMode(m_mappingMode
);
1049 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1051 m_signX
= xLeftRight
? 1 : -1;
1052 m_signY
= yBottomUp
? -1 : 1;
1054 SetMapMode(m_mappingMode
);
1057 void wxDC::SetSystemScale(double x
, double y
)
1062 SetMapMode(m_mappingMode
);
1065 void wxDC::SetLogicalOrigin(long x
, long y
)
1067 m_logicalOriginX
= x
;
1068 m_logicalOriginY
= y
;
1070 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1073 void wxDC::SetDeviceOrigin(long x
, long y
)
1075 m_deviceOriginX
= x
;
1076 m_deviceOriginY
= y
;
1078 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1081 // ---------------------------------------------------------------------------
1082 // coordinates transformations
1083 // ---------------------------------------------------------------------------
1085 long wxDCBase::DeviceToLogicalX(long x
) const
1087 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1090 long wxDCBase::DeviceToLogicalXRel(long x
) const
1092 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1095 long wxDCBase::DeviceToLogicalY(long y
) const
1097 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1100 long wxDCBase::DeviceToLogicalYRel(long y
) const
1102 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1105 long wxDCBase::LogicalToDeviceX(long x
) const
1107 return (long) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1110 long wxDCBase::LogicalToDeviceXRel(long x
) const
1112 return (long) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1115 long wxDCBase::LogicalToDeviceY(long y
) const
1117 return (long) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1120 long wxDCBase::LogicalToDeviceYRel(long y
) const
1122 return (long) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1125 // ---------------------------------------------------------------------------
1127 // ---------------------------------------------------------------------------
1128 bool wxDC::DoBlit(long xdest
, long ydest
, long width
, long height
,
1129 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1131 long xdest1
= xdest
;
1132 long ydest1
= ydest
;
1136 // Chris Breeze 18/5/98: use text foreground/background colours
1137 // when blitting from 1-bit bitmaps
1138 COLORREF old_textground
= ::GetTextColor(GetHdc());
1139 COLORREF old_background
= ::GetBkColor(GetHdc());
1140 if (m_textForegroundColour
.Ok())
1142 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1144 if (m_textBackgroundColour
.Ok())
1146 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1149 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1150 rop
== wxCLEAR
? WHITENESS
:
1151 rop
== wxSET
? BLACKNESS
:
1152 rop
== wxINVERT
? DSTINVERT
:
1153 rop
== wxAND
? MERGECOPY
:
1154 rop
== wxOR
? MERGEPAINT
:
1155 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1156 rop
== wxXOR
? SRCINVERT
:
1157 rop
== wxOR_REVERSE
? MERGEPAINT
:
1158 rop
== wxAND_REVERSE
? SRCERASE
:
1159 rop
== wxSRC_OR
? SRCPAINT
:
1160 rop
== wxSRC_AND
? SRCAND
:
1163 bool success
= TRUE
;
1164 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1168 // Not implemented under Win95 (or maybe a specific device?)
1169 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1170 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1180 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1181 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1182 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1183 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1184 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1185 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1186 ::SelectObject(dc_mask
, 0);
1187 ::DeleteDC(dc_mask
);
1189 // New code from Chris Breeze, 15/7/98
1190 // Blit bitmap with mask
1192 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1194 // If we are printing source colours are screen colours
1195 // not printer colours and so we need copy the bitmap
1198 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1199 HDC dc_src
= (HDC
) source
->m_hDC
;
1201 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1202 for (int x
= 0; x
< width
; x
++)
1204 for (int y
= 0; y
< height
; y
++)
1206 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1209 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1210 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1211 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1212 ::FillRect(GetHdc(), &rect
, brush
);
1213 ::DeleteObject(brush
);
1217 ::SelectObject(dc_mask
, 0);
1218 ::DeleteDC(dc_mask
);
1222 // create a temp buffer bitmap and DCs to access it and the mask
1223 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1224 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1225 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1226 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1227 ::SelectObject(dc_buffer
, buffer_bmap
);
1229 // copy dest to buffer
1230 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1231 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1233 // copy src to buffer using selected raster op
1234 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1235 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1237 // set masked area in buffer to BLACK (pixel value 0)
1238 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1239 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1240 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1241 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1243 // set unmasked area in dest to BLACK
1244 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1245 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1246 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1247 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1248 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1249 ::SetTextColor(GetHdc(), prevCol
);
1251 // OR buffer to dest
1252 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1253 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1255 // tidy up temporary DCs and bitmap
1256 ::SelectObject(dc_mask
, 0);
1257 ::DeleteDC(dc_mask
);
1258 ::SelectObject(dc_buffer
, 0);
1259 ::DeleteDC(dc_buffer
);
1260 ::DeleteObject(buffer_bmap
);
1266 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1268 // If we are printing, source colours are screen colours
1269 // not printer colours and so we need copy the bitmap
1271 HDC dc_src
= (HDC
) source
->m_hDC
;
1273 for (int x
= 0; x
< width
; x
++)
1275 for (int y
= 0; y
< height
; y
++)
1277 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1278 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1279 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1280 ::FillRect(GetHdc(), &rect
, brush
);
1281 ::DeleteObject(brush
);
1287 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1288 xsrc1
, ysrc1
, dwRop
) != 0);
1291 ::SetTextColor(GetHdc(), old_textground
);
1292 ::SetBkColor(GetHdc(), old_background
);
1297 void wxDC::DoGetSize(int *w
, int *h
) const
1299 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1300 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1303 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1305 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1306 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1309 wxSize
wxDC::GetPPI() const
1311 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1312 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1314 return wxSize(x
, y
);
1317 // For use by wxWindows only, unless custom units are required.
1318 void wxDC::SetLogicalScale(double x
, double y
)
1320 m_logicalScaleX
= x
;
1321 m_logicalScaleY
= y
;
1324 #if WXWIN_COMPATIBILITY
1325 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1326 float *descent
, float *externalLeading
,
1327 wxFont
*theFont
, bool use16bit
) const
1329 long x1
, y1
, descent1
, externalLeading1
;
1330 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1333 *descent
= descent1
;
1334 if (externalLeading
)
1335 *externalLeading
= externalLeading1
;
1339 // ---------------------------------------------------------------------------
1340 // spline drawing code
1341 // ---------------------------------------------------------------------------
1345 class wxSpline
: public wxObject
1351 wxSpline(wxList
*list
);
1352 void DeletePoints();
1354 // Doesn't delete points
1358 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1360 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1361 double a3
, double b3
, double a4
, double b4
);
1362 void wx_clear_stack();
1363 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1364 double *y3
, double *x4
, double *y4
);
1365 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1366 double x4
, double y4
);
1367 static bool wx_spline_add_point(double x
, double y
);
1368 static void wx_spline_draw_point_array(wxDC
*dc
);
1369 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1371 void wxDC::DoDrawSpline(wxList
*list
)
1373 wxSpline
spline(list
);
1375 wx_draw_open_spline(this, &spline
);
1378 wxList wx_spline_point_list
;
1380 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1383 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1384 double x1
, y1
, x2
, y2
;
1386 wxNode
*node
= spline
->points
->First();
1387 p
= (wxPoint
*)node
->Data();
1392 node
= node
->Next();
1393 p
= (wxPoint
*)node
->Data();
1397 cx1
= (double)((x1
+ x2
) / 2);
1398 cy1
= (double)((y1
+ y2
) / 2);
1399 cx2
= (double)((cx1
+ x2
) / 2);
1400 cy2
= (double)((cy1
+ y2
) / 2);
1402 wx_spline_add_point(x1
, y1
);
1404 while ((node
= node
->Next()) != NULL
)
1406 p
= (wxPoint
*)node
->Data();
1411 cx4
= (double)(x1
+ x2
) / 2;
1412 cy4
= (double)(y1
+ y2
) / 2;
1413 cx3
= (double)(x1
+ cx4
) / 2;
1414 cy3
= (double)(y1
+ cy4
) / 2;
1416 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1420 cx2
= (double)(cx1
+ x2
) / 2;
1421 cy2
= (double)(cy1
+ y2
) / 2;
1424 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1425 wx_spline_add_point(x2
, y2
);
1427 wx_spline_draw_point_array(dc
);
1431 /********************* CURVES FOR SPLINES *****************************
1433 The following spline drawing routine is from
1435 "An Algorithm for High-Speed Curve Generation"
1436 by George Merrill Chaikin,
1437 Computer Graphics and Image Processing, 3, Academic Press,
1442 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1443 Computer Graphics and Image Processing, 4, Academic Press,
1446 ***********************************************************************/
1448 #define half(z1, z2) ((z1+z2)/2.0)
1451 /* iterative version */
1453 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1456 register double xmid
, ymid
;
1457 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1460 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1462 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1463 xmid
= (double)half(x2
, x3
);
1464 ymid
= (double)half(y2
, y3
);
1465 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1466 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1467 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1468 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1470 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1471 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1472 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1473 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1479 /* utilities used by spline drawing routines */
1482 typedef struct wx_spline_stack_struct
{
1483 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1487 #define SPLINE_STACK_DEPTH 20
1488 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1489 static Stack
*wx_stack_top
;
1490 static int wx_stack_count
;
1492 void wx_clear_stack()
1494 wx_stack_top
= wx_spline_stack
;
1498 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1500 wx_stack_top
->x1
= x1
;
1501 wx_stack_top
->y1
= y1
;
1502 wx_stack_top
->x2
= x2
;
1503 wx_stack_top
->y2
= y2
;
1504 wx_stack_top
->x3
= x3
;
1505 wx_stack_top
->y3
= y3
;
1506 wx_stack_top
->x4
= x4
;
1507 wx_stack_top
->y4
= y4
;
1512 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1513 double *x3
, double *y3
, double *x4
, double *y4
)
1515 if (wx_stack_count
== 0)
1519 *x1
= wx_stack_top
->x1
;
1520 *y1
= wx_stack_top
->y1
;
1521 *x2
= wx_stack_top
->x2
;
1522 *y2
= wx_stack_top
->y2
;
1523 *x3
= wx_stack_top
->x3
;
1524 *y3
= wx_stack_top
->y3
;
1525 *x4
= wx_stack_top
->x4
;
1526 *y4
= wx_stack_top
->y4
;
1530 static bool wx_spline_add_point(double x
, double y
)
1532 wxPoint
*point
= new wxPoint
;
1535 wx_spline_point_list
.Append((wxObject
*)point
);
1539 static void wx_spline_draw_point_array(wxDC
*dc
)
1541 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1542 wxNode
*node
= wx_spline_point_list
.First();
1545 wxPoint
*point
= (wxPoint
*)node
->Data();
1548 node
= wx_spline_point_list
.First();
1552 wxSpline::wxSpline(wxList
*list
)
1557 wxSpline::~wxSpline()
1561 void wxSpline::DeletePoints()
1563 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1565 wxPoint
*point
= (wxPoint
*)node
->Data();
1573 #endif // wxUSE_SPLINES