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
49 #if wxUSE_NORLANDER_HEADERS
59 #include "wx/msw/private.h"
61 #if !USE_SHARED_LIBRARY
62 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
65 // ---------------------------------------------------------------------------
67 // ---------------------------------------------------------------------------
69 static const int VIEWPORT_EXTENT
= 1000;
71 static const int MM_POINTS
= 9;
72 static const int MM_METRIC
= 10;
74 // ===========================================================================
76 // ===========================================================================
78 // ---------------------------------------------------------------------------
80 // ---------------------------------------------------------------------------
82 // Default constructor
96 m_windowExtX
= VIEWPORT_EXTENT
;
97 m_windowExtY
= VIEWPORT_EXTENT
;
106 SelectOldObjects(m_hDC
);
108 if ( m_canvas
== NULL
)
109 ::DeleteDC(GetHdc());
111 ::ReleaseDC((HWND
)m_canvas
->GetHWND(), GetHdc());
117 // This will select current objects out of the DC,
118 // which is what you have to do before deleting the
120 void wxDC::SelectOldObjects(WXHDC dc
)
126 ::SelectObject((HDC
) dc
, (HBITMAP
) m_oldBitmap
);
127 if (m_selectedBitmap
.Ok())
129 m_selectedBitmap
.SetSelectedInto(NULL
);
135 ::SelectObject((HDC
) dc
, (HPEN
) m_oldPen
);
140 ::SelectObject((HDC
) dc
, (HBRUSH
) m_oldBrush
);
145 ::SelectObject((HDC
) dc
, (HFONT
) m_oldFont
);
150 ::SelectPalette((HDC
) dc
, (HPALETTE
) m_oldPalette
, TRUE
);
155 m_brush
= wxNullBrush
;
157 m_palette
= wxNullPalette
;
159 m_backgroundBrush
= wxNullBrush
;
160 m_selectedBitmap
= wxNullBitmap
;
163 // ---------------------------------------------------------------------------
165 // ---------------------------------------------------------------------------
167 void wxDC::DoSetClippingRegion(wxCoord cx
, wxCoord cy
, wxCoord cw
, wxCoord ch
)
172 m_clipX2
= (int)(cx
+ cw
);
173 m_clipY2
= (int)(cy
+ ch
);
175 DoClipping((WXHDC
) m_hDC
);
178 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
180 wxCHECK_RET( region
.GetHRGN(), wxT("invalid clipping region") );
182 wxRect box
= region
.GetBox();
187 m_clipX2
= box
.x
+ box
.width
;
188 m_clipY2
= box
.y
+ box
.height
;
191 SelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN());
193 ExtSelectClipRgn(GetHdc(), (HRGN
) region
.GetHRGN(), RGN_AND
);
197 void wxDC::DoClipping(WXHDC dc
)
199 if (m_clipping
&& dc
)
201 IntersectClipRect((HDC
) dc
, XLOG2DEV(m_clipX1
), YLOG2DEV(m_clipY1
),
202 XLOG2DEV(m_clipX2
), YLOG2DEV(m_clipY2
));
206 void wxDC::DestroyClippingRegion()
208 if (m_clipping
&& m_hDC
)
210 // TODO: this should restore the previous clipping region,
211 // so that OnPaint processing works correctly, and the update clipping region
212 // doesn't get destroyed after the first DestroyClippingRegion.
213 HRGN rgn
= CreateRectRgn(0, 0, 32000, 32000);
214 SelectClipRgn(GetHdc(), rgn
);
220 // ---------------------------------------------------------------------------
221 // query capabilities
222 // ---------------------------------------------------------------------------
224 bool wxDC::CanDrawBitmap() const
229 bool wxDC::CanGetTextExtent() const
231 // What sort of display is it?
232 int technology
= ::GetDeviceCaps(GetHdc(), TECHNOLOGY
);
234 return (technology
== DT_RASDISPLAY
) || (technology
== DT_RASPRINTER
);
237 int wxDC::GetDepth() const
239 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL
);
242 // ---------------------------------------------------------------------------
244 // ---------------------------------------------------------------------------
251 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
255 wxCHECK_RET( m_selectedBitmap
.Ok(), wxT("this DC can't be cleared") );
257 rect
.left
= 0; rect
.top
= 0;
258 rect
.right
= m_selectedBitmap
.GetWidth();
259 rect
.bottom
= m_selectedBitmap
.GetHeight();
262 (void) ::SetMapMode(GetHdc(), MM_TEXT
);
264 DWORD colour
= GetBkColor(GetHdc());
265 HBRUSH brush
= CreateSolidBrush(colour
);
266 FillRect(GetHdc(), &rect
, brush
);
269 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
270 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
271 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
272 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
273 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
276 void wxDC::DoFloodFill(wxCoord x
, wxCoord y
, const wxColour
& col
, int style
)
278 (void)ExtFloodFill(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
280 style
== wxFLOOD_SURFACE
? FLOODFILLSURFACE
283 CalcBoundingBox(x
, y
);
286 bool wxDC::DoGetPixel(wxCoord x
, wxCoord y
, wxColour
*col
) const
288 // added by steve 29.12.94 (copied from DrawPoint)
289 // returns TRUE for pixels in the color of the current pen
290 // and FALSE for all other pixels colors
291 // if col is non-NULL return the color of the pixel
293 // get the color of the pixel
294 COLORREF pixelcolor
= ::GetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
));
295 // get the color of the pen
296 COLORREF pencolor
= 0x00ffffff;
299 pencolor
= m_pen
.GetColour().GetPixel();
302 // return the color of the pixel
304 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
306 // check, if color of the pixels is the same as the color
307 // of the current pen
308 return(pixelcolor
==pencolor
);
311 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
313 wxCoord x1
= x
-VIEWPORT_EXTENT
;
314 wxCoord y1
= y
-VIEWPORT_EXTENT
;
315 wxCoord x2
= x
+VIEWPORT_EXTENT
;
316 wxCoord y2
= y
+VIEWPORT_EXTENT
;
318 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
319 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y
));
321 (void)MoveToEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
322 (void)LineTo(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y2
));
324 CalcBoundingBox(x1
, y1
);
325 CalcBoundingBox(x2
, y2
);
328 void wxDC::DoDrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
330 (void)MoveToEx(GetHdc(), XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
331 (void)LineTo(GetHdc(), XLOG2DEV(x2
), YLOG2DEV(y2
));
333 /* MATTHEW: [6] New normalization */
334 #if WX_STANDARD_GRAPHICS
335 (void)LineTo(GetHdc(), XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
338 CalcBoundingBox(x1
, y1
);
339 CalcBoundingBox(x2
, y2
);
342 void wxDC::DoDrawArc(wxCoord x1
,wxCoord y1
,wxCoord x2
,wxCoord y2
, wxCoord xc
, wxCoord yc
)
346 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
347 if (x1
==x2
&& x2
==y2
)
349 DrawEllipse(xc
,yc
,(wxCoord
)(radius
*2.0),(wxCoord
)(radius
*2.0));
353 wxCoord xx1
= XLOG2DEV(x1
);
354 wxCoord yy1
= YLOG2DEV(y1
);
355 wxCoord xx2
= XLOG2DEV(x2
);
356 wxCoord yy2
= YLOG2DEV(y2
);
357 wxCoord xxc
= XLOG2DEV(xc
);
358 wxCoord yyc
= YLOG2DEV(yc
);
359 wxCoord ray
= (wxCoord
) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
)));
361 (void)MoveToEx(GetHdc(), (int) xx1
, (int) yy1
, NULL
);
362 wxCoord xxx1
= (wxCoord
) (xxc
-ray
);
363 wxCoord yyy1
= (wxCoord
) (yyc
-ray
);
364 wxCoord xxx2
= (wxCoord
) (xxc
+ray
);
365 wxCoord yyy2
= (wxCoord
) (yyc
+ray
);
366 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
368 // Have to add 1 to bottom-right corner of rectangle
369 // to make semi-circles look right (crooked line otherwise).
370 // Unfortunately this is not a reliable method, depends
371 // on the size of shape.
372 // TODO: figure out why this happens!
373 Pie(GetHdc(),xxx1
,yyy1
,xxx2
+1,yyy2
+1,
377 Arc(GetHdc(),xxx1
,yyy1
,xxx2
,yyy2
,
380 CalcBoundingBox((wxCoord
)(xc
-radius
), (wxCoord
)(yc
-radius
));
381 CalcBoundingBox((wxCoord
)(xc
+radius
), (wxCoord
)(yc
+radius
));
384 void wxDC::DoDrawPoint(wxCoord x
, wxCoord y
)
386 COLORREF color
= 0x00ffffff;
389 color
= m_pen
.GetColour().GetPixel();
392 SetPixel(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), color
);
394 CalcBoundingBox(x
, y
);
397 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int fillStyle
)
399 // Do things less efficiently if we have offsets
400 if (xoffset
!= 0 || yoffset
!= 0)
402 POINT
*cpoints
= new POINT
[n
];
404 for (i
= 0; i
< n
; i
++)
406 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
407 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
409 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
411 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
412 (void)Polygon(GetHdc(), cpoints
, n
);
413 SetPolyFillMode(GetHdc(),prev
);
419 for (i
= 0; i
< n
; i
++)
420 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
422 int prev
= SetPolyFillMode(GetHdc(),fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
);
423 (void)Polygon(GetHdc(), (POINT
*) points
, n
);
424 SetPolyFillMode(GetHdc(),prev
);
428 void wxDC::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
430 // Do things less efficiently if we have offsets
431 if (xoffset
!= 0 || yoffset
!= 0)
433 POINT
*cpoints
= new POINT
[n
];
435 for (i
= 0; i
< n
; i
++)
437 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
438 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
440 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
442 (void)Polyline(GetHdc(), cpoints
, n
);
448 for (i
= 0; i
< n
; i
++)
449 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
451 (void)Polyline(GetHdc(), (POINT
*) points
, n
);
455 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
457 wxCoord x2
= x
+ width
;
458 wxCoord y2
= y
+ height
;
460 /* MATTHEW: [6] new normalization */
461 #if WX_STANDARD_GRAPHICS
462 bool do_brush
, do_pen
;
464 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
465 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
468 HPEN orig_pen
= NULL
;
470 if (do_pen
|| !m_pen
.Ok())
471 orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
473 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
474 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
476 if (do_pen
|| !m_pen
.Ok())
477 ::SelectObject(GetHdc() , orig_pen
);
480 HBRUSH orig_brush
= NULL
;
482 if (do_brush
|| !m_brush
.Ok())
483 orig_brush
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
485 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
),
486 XLOG2DEV(x2
), YLOG2DEV(y2
));
488 if (do_brush
|| !m_brush
.Ok())
489 ::SelectObject(GetHdc(), orig_brush
);
492 (void)Rectangle(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
495 CalcBoundingBox(x
, y
);
496 CalcBoundingBox(x2
, y2
);
499 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
501 // Now, a negative radius value is interpreted to mean
502 // 'the proportion of the smallest X or Y dimension'
506 double smallest
= 0.0;
511 radius
= (- radius
* smallest
);
514 wxCoord x2
= (x
+width
);
515 wxCoord y2
= (y
+height
);
517 (void)RoundRect(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
518 YLOG2DEV(y2
), (int) (2*XLOG2DEV(radius
)), (int)( 2*YLOG2DEV(radius
)));
520 CalcBoundingBox(x
, y
);
521 CalcBoundingBox(x2
, y2
);
524 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
526 wxCoord x2
= (x
+width
);
527 wxCoord y2
= (y
+height
);
529 (void)Ellipse(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
531 CalcBoundingBox(x
, y
);
532 CalcBoundingBox(x2
, y2
);
535 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
536 void wxDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
541 const double deg2rad
= 3.14159265359 / 180.0;
542 int rx1
= XLOG2DEV(x
+w
/2);
543 int ry1
= YLOG2DEV(y
+h
/2);
546 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
547 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
548 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
549 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
551 // draw pie with NULL_PEN first and then outline otherwise a line is
552 // drawn from the start and end points to the centre
553 HPEN orig_pen
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
) ::GetStockObject(NULL_PEN
));
556 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
561 (void)Pie(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
562 rx1
, ry1
-1, rx2
, ry2
-1);
564 ::SelectObject(GetHdc(), orig_pen
);
565 (void)Arc(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
568 CalcBoundingBox(x
, y
);
569 CalcBoundingBox(x2
, y2
);
572 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
574 #if defined(__WIN32__) && !defined(__SC__) && !defined(__TWIN32__)
575 ::DrawIconEx(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON(),
576 icon
.GetWidth(), icon
.GetHeight(), 0, 0, DI_NORMAL
);
578 ::DrawIcon(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
581 CalcBoundingBox(x
, y
);
582 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
585 void wxDC::DoDrawBitmap( const wxBitmap
&bmp
, wxCoord x
, wxCoord y
, bool useMask
)
590 // If we're not drawing transparently, and not drawing to a printer,
591 // optimize this function to use Windows functions.
592 if (!useMask
&& !IsKindOf(CLASSINFO(wxPrinterDC
)))
595 HDC memdc
= ::CreateCompatibleDC( cdc
);
596 HBITMAP hbitmap
= (HBITMAP
) bmp
.GetHBITMAP( );
598 wxASSERT_MSG( hbitmap
, wxT("bitmap is ok but HBITMAP is NULL?") );
600 ::SelectObject( memdc
, hbitmap
);
601 ::BitBlt( cdc
, x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), memdc
, 0, 0, SRCCOPY
);
606 // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level
608 memDC
.SelectObject(bmp
);
610 /* Not sure if we need this. The mask should leave the
611 * masked areas as per the original background of this DC.
614 // There might be transparent areas, so make these
615 // the same colour as this DC
616 memDC.SetBackground(* GetBackground());
620 Blit(x
, y
, bmp
.GetWidth(), bmp
.GetHeight(), & memDC
, 0, 0, wxCOPY
, useMask
);
622 memDC
.SelectObject(wxNullBitmap
);
626 void wxDC::DoDrawText(const wxString
& text
, wxCoord x
, wxCoord y
)
628 if (m_textForegroundColour
.Ok())
629 SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
631 DWORD old_background
= 0;
632 if (m_textBackgroundColour
.Ok())
634 old_background
= SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
637 if (m_backgroundMode
== wxTRANSPARENT
)
638 SetBkMode(GetHdc(), TRANSPARENT
);
640 SetBkMode(GetHdc(), OPAQUE
);
642 (void)TextOut(GetHdc(), XLOG2DEV(x
), YLOG2DEV(y
), WXSTRINGCAST text
, wxStrlen(WXSTRINGCAST text
));
644 if (m_textBackgroundColour
.Ok())
645 (void)SetBkColor(GetHdc(), old_background
);
647 // background colour is used only for DrawText, otherwise
648 // always TRANSPARENT, RR
649 SetBkMode(GetHdc(), TRANSPARENT
);
651 CalcBoundingBox(x
, y
);
654 GetTextExtent(text
, &w
, &h
);
655 CalcBoundingBox((x
+ w
), (y
+ h
));
658 void wxDC::DoDrawRotatedText(const wxString
& text
,
659 wxCoord x
, wxCoord y
,
662 wxFAIL_MSG( _T("TODO") );
665 // ---------------------------------------------------------------------------
667 // ---------------------------------------------------------------------------
669 void wxDC::SetPalette(const wxPalette
& palette
)
671 // Set the old object temporarily, in case the assignment deletes an object
672 // that's not yet selected out.
675 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
683 // Setting a NULL colourmap is a way of restoring
684 // the original colourmap
687 ::SelectPalette(GetHdc(), (HPALETTE
) m_oldPalette
, TRUE
);
694 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
696 HPALETTE oldPal
= ::SelectPalette(GetHdc(), (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
698 m_oldPalette
= (WXHPALETTE
) oldPal
;
700 ::RealizePalette(GetHdc());
704 void wxDC::SetFont(const wxFont
& the_font
)
706 // Set the old object temporarily, in case the assignment deletes an object
707 // that's not yet selected out.
710 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
719 ::SelectObject(GetHdc(), (HFONT
) m_oldFont
);
723 if (m_font
.Ok() && m_font
.GetResourceHandle())
725 HFONT f
= (HFONT
) ::SelectObject(GetHdc(), (HFONT
) m_font
.GetResourceHandle());
726 if (f
== (HFONT
) NULL
)
728 wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
731 m_oldFont
= (WXHFONT
) f
;
735 void wxDC::SetPen(const wxPen
& pen
)
737 // Set the old object temporarily, in case the assignment deletes an object
738 // that's not yet selected out.
741 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
750 ::SelectObject(GetHdc(), (HPEN
) m_oldPen
);
756 if (m_pen
.GetResourceHandle())
758 HPEN p
= (HPEN
) ::SelectObject(GetHdc(), (HPEN
)m_pen
.GetResourceHandle());
760 m_oldPen
= (WXHPEN
) p
;
765 void wxDC::SetBrush(const wxBrush
& brush
)
767 // Set the old object temporarily, in case the assignment deletes an object
768 // that's not yet selected out.
771 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
780 ::SelectObject(GetHdc(), (HBRUSH
) m_oldBrush
);
786 if (m_brush
.GetResourceHandle())
789 b
= (HBRUSH
) ::SelectObject(GetHdc(), (HBRUSH
)m_brush
.GetResourceHandle());
791 m_oldBrush
= (WXHBRUSH
) b
;
796 void wxDC::SetBackground(const wxBrush
& brush
)
798 m_backgroundBrush
= brush
;
800 if (!m_backgroundBrush
.Ok())
805 bool customColours
= TRUE
;
806 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
807 // change background colours from the control-panel specified colours.
808 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
809 customColours
= FALSE
;
813 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
815 m_canvas
->SetTransparent(TRUE
);
819 // New behaviour, 10/2/99: setting the background brush of a DC
820 // doesn't affect the window background colour. However,
821 // I'm leaving in the transparency setting because it's needed by
822 // various controls (e.g. wxStaticText) to determine whether to draw
823 // transparently or not. TODO: maybe this should be a new function
824 // wxWindow::SetTransparency(). Should that apply to the child itself, or the
826 // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
827 m_canvas
->SetTransparent(FALSE
);
831 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel();
833 (void)SetBkColor(GetHdc(), new_color
);
837 void wxDC::SetBackgroundMode(int mode
)
839 m_backgroundMode
= mode
;
841 // SetBackgroundColour now only refers to text background
842 // and m_backgroundMode is used there
845 if (m_backgroundMode == wxTRANSPARENT)
846 ::SetBkMode(GetHdc(), TRANSPARENT);
848 ::SetBkMode(GetHdc(), OPAQUE);
852 void wxDC::SetLogicalFunction(int function
)
854 m_logicalFunction
= function
;
856 SetRop((WXHDC
) m_hDC
);
859 void wxDC::SetRop(WXHDC dc
)
861 if (!dc
|| m_logicalFunction
< 0)
865 // These may be wrong
866 switch (m_logicalFunction
)
868 // case wxXOR: c_rop = R2_XORPEN; break;
869 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
870 case wxINVERT
: c_rop
= R2_NOT
; break;
871 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
872 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
873 case wxCLEAR
: c_rop
= R2_WHITE
; break;
874 case wxSET
: c_rop
= R2_BLACK
; break;
875 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
876 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
877 case wxAND
: c_rop
= R2_MASKPEN
; break;
878 case wxOR
: c_rop
= R2_MERGEPEN
; break;
879 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
884 c_rop
= R2_COPYPEN
; break;
886 SetROP2((HDC
) dc
, c_rop
);
889 bool wxDC::StartDoc(const wxString
& message
)
891 // We might be previewing, so return TRUE to let it continue.
899 void wxDC::StartPage()
907 // ---------------------------------------------------------------------------
909 // ---------------------------------------------------------------------------
911 wxCoord
wxDC::GetCharHeight() const
913 TEXTMETRIC lpTextMetric
;
915 GetTextMetrics(GetHdc(), &lpTextMetric
);
917 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
920 wxCoord
wxDC::GetCharWidth() const
922 TEXTMETRIC lpTextMetric
;
924 GetTextMetrics(GetHdc(), &lpTextMetric
);
926 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
929 void wxDC::DoGetTextExtent(const wxString
& string
, wxCoord
*x
, wxCoord
*y
,
930 wxCoord
*descent
, wxCoord
*externalLeading
,
931 wxFont
*theFont
) const
933 wxFont
*fontToUse
= (wxFont
*) theFont
;
935 fontToUse
= (wxFont
*) &m_font
;
940 GetTextExtentPoint(GetHdc(), WXSTRINGCAST string
, wxStrlen(WXSTRINGCAST string
), &sizeRect
);
941 GetTextMetrics(GetHdc(), &tm
);
943 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
944 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
945 if (descent
) *descent
= tm
.tmDescent
;
946 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
949 void wxDC::SetMapMode(int mode
)
951 m_mappingMode
= mode
;
954 int pixel_height
= 0;
958 pixel_width
= GetDeviceCaps(GetHdc(), HORZRES
);
959 pixel_height
= GetDeviceCaps(GetHdc(), VERTRES
);
960 mm_width
= GetDeviceCaps(GetHdc(), HORZSIZE
);
961 mm_height
= GetDeviceCaps(GetHdc(), VERTSIZE
);
963 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
968 double mm2pixelsX
= pixel_width
/mm_width
;
969 double mm2pixelsY
= pixel_height
/mm_height
;
975 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
976 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
981 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
982 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
987 m_logicalScaleX
= mm2pixelsX
;
988 m_logicalScaleY
= mm2pixelsY
;
993 m_logicalScaleX
= (mm2pixelsX
/10.0);
994 m_logicalScaleY
= (mm2pixelsY
/10.0);
1000 m_logicalScaleX
= 1.0;
1001 m_logicalScaleY
= 1.0;
1006 if (::GetMapMode(GetHdc()) != MM_ANISOTROPIC
)
1007 ::SetMapMode(GetHdc(), MM_ANISOTROPIC
);
1009 SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1010 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1011 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1012 ::SetWindowExtEx(GetHdc(), m_windowExtX
, m_windowExtY
, NULL
);
1013 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1014 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1017 void wxDC::SetUserScale(double x
, double y
)
1022 SetMapMode(m_mappingMode
);
1025 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1027 m_signX
= xLeftRight
? 1 : -1;
1028 m_signY
= yBottomUp
? -1 : 1;
1030 SetMapMode(m_mappingMode
);
1033 void wxDC::SetSystemScale(double x
, double y
)
1038 SetMapMode(m_mappingMode
);
1041 void wxDC::SetLogicalOrigin(wxCoord x
, wxCoord y
)
1043 m_logicalOriginX
= x
;
1044 m_logicalOriginY
= y
;
1046 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1049 void wxDC::SetDeviceOrigin(wxCoord x
, wxCoord y
)
1051 m_deviceOriginX
= x
;
1052 m_deviceOriginY
= y
;
1054 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1057 // ---------------------------------------------------------------------------
1058 // coordinates transformations
1059 // ---------------------------------------------------------------------------
1061 wxCoord
wxDCBase::DeviceToLogicalX(wxCoord x
) const
1063 return (wxCoord
) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
) - m_logicalOriginX
);
1066 wxCoord
wxDCBase::DeviceToLogicalXRel(wxCoord x
) const
1068 return (wxCoord
) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
));
1071 wxCoord
wxDCBase::DeviceToLogicalY(wxCoord y
) const
1073 return (wxCoord
) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
) - m_logicalOriginY
);
1076 wxCoord
wxDCBase::DeviceToLogicalYRel(wxCoord y
) const
1078 return (wxCoord
) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
));
1081 wxCoord
wxDCBase::LogicalToDeviceX(wxCoord x
) const
1083 return (wxCoord
) ((x
- m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
+ m_deviceOriginX
);
1086 wxCoord
wxDCBase::LogicalToDeviceXRel(wxCoord x
) const
1088 return (wxCoord
) (x
*m_logicalScaleX
*m_userScaleX
*m_signX
*m_scaleX
);
1091 wxCoord
wxDCBase::LogicalToDeviceY(wxCoord y
) const
1093 return (wxCoord
) ((y
- m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
+ m_deviceOriginY
);
1096 wxCoord
wxDCBase::LogicalToDeviceYRel(wxCoord y
) const
1098 return (wxCoord
) (y
*m_logicalScaleY
*m_userScaleY
*m_signY
*m_scaleY
);
1101 // ---------------------------------------------------------------------------
1103 // ---------------------------------------------------------------------------
1104 bool wxDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
1105 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
, int rop
, bool useMask
)
1107 wxCoord xdest1
= xdest
;
1108 wxCoord ydest1
= ydest
;
1109 wxCoord xsrc1
= xsrc
;
1110 wxCoord ysrc1
= ysrc
;
1112 // Chris Breeze 18/5/98: use text foreground/background colours
1113 // when blitting from 1-bit bitmaps
1114 COLORREF old_textground
= ::GetTextColor(GetHdc());
1115 COLORREF old_background
= ::GetBkColor(GetHdc());
1116 if (m_textForegroundColour
.Ok())
1118 ::SetTextColor(GetHdc(), m_textForegroundColour
.GetPixel() );
1120 if (m_textBackgroundColour
.Ok())
1122 ::SetBkColor(GetHdc(), m_textBackgroundColour
.GetPixel() );
1125 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1126 rop
== wxCLEAR
? WHITENESS
:
1127 rop
== wxSET
? BLACKNESS
:
1128 rop
== wxINVERT
? DSTINVERT
:
1129 rop
== wxAND
? MERGECOPY
:
1130 rop
== wxOR
? MERGEPAINT
:
1131 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1132 rop
== wxXOR
? SRCINVERT
:
1133 rop
== wxOR_REVERSE
? MERGEPAINT
:
1134 rop
== wxAND_REVERSE
? SRCERASE
:
1135 rop
== wxSRC_OR
? SRCPAINT
:
1136 rop
== wxSRC_AND
? SRCAND
:
1139 bool success
= TRUE
;
1140 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1144 // Not implemented under Win95 (or maybe a specific device?)
1145 if (MaskBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1146 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1156 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1157 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1158 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1159 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1160 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1161 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1162 ::SelectObject(dc_mask
, 0);
1163 ::DeleteDC(dc_mask
);
1165 // New code from Chris Breeze, 15/7/98
1166 // Blit bitmap with mask
1168 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1170 // If we are printing source colours are screen colours
1171 // not printer colours and so we need copy the bitmap
1174 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1175 HDC dc_src
= (HDC
) source
->m_hDC
;
1177 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1178 for (int x
= 0; x
< width
; x
++)
1180 for (int y
= 0; y
< height
; y
++)
1182 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1185 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1186 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1187 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1188 ::FillRect(GetHdc(), &rect
, brush
);
1189 ::DeleteObject(brush
);
1193 ::SelectObject(dc_mask
, 0);
1194 ::DeleteDC(dc_mask
);
1198 // create a temp buffer bitmap and DCs to access it and the mask
1199 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1200 HDC dc_buffer
= ::CreateCompatibleDC(GetHdc());
1201 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap(GetHdc(), width
, height
);
1202 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1203 ::SelectObject(dc_buffer
, buffer_bmap
);
1205 // copy dest to buffer
1206 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1207 GetHdc(), xdest1
, ydest1
, SRCCOPY
);
1209 // copy src to buffer using selected raster op
1210 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1211 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1213 // set masked area in buffer to BLACK (pixel value 0)
1214 COLORREF prevBkCol
= ::SetBkColor(GetHdc(), RGB(255, 255, 255));
1215 COLORREF prevCol
= ::SetTextColor(GetHdc(), RGB(0, 0, 0));
1216 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1217 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1219 // set unmasked area in dest to BLACK
1220 ::SetBkColor(GetHdc(), RGB(0, 0, 0));
1221 ::SetTextColor(GetHdc(), RGB(255, 255, 255));
1222 ::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1223 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1224 ::SetBkColor(GetHdc(), prevBkCol
); // restore colours to original values
1225 ::SetTextColor(GetHdc(), prevCol
);
1227 // OR buffer to dest
1228 success
= (::BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
,
1229 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1231 // tidy up temporary DCs and bitmap
1232 ::SelectObject(dc_mask
, 0);
1233 ::DeleteDC(dc_mask
);
1234 ::SelectObject(dc_buffer
, 0);
1235 ::DeleteDC(dc_buffer
);
1236 ::DeleteObject(buffer_bmap
);
1242 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1244 // If we are printing, source colours are screen colours
1245 // not printer colours and so we need copy the bitmap
1247 HDC dc_src
= (HDC
) source
->m_hDC
;
1249 for (int x
= 0; x
< width
; x
++)
1251 for (int y
= 0; y
< height
; y
++)
1253 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1254 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1255 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1256 ::FillRect(GetHdc(), &rect
, brush
);
1257 ::DeleteObject(brush
);
1263 success
= (BitBlt(GetHdc(), xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1264 xsrc1
, ysrc1
, dwRop
) != 0);
1267 ::SetTextColor(GetHdc(), old_textground
);
1268 ::SetBkColor(GetHdc(), old_background
);
1273 void wxDC::DoGetSize(int *w
, int *h
) const
1275 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZRES
);
1276 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTRES
);
1279 void wxDC::DoGetSizeMM(int *w
, int *h
) const
1281 if ( w
) *w
= ::GetDeviceCaps(GetHdc(), HORZSIZE
);
1282 if ( h
) *h
= ::GetDeviceCaps(GetHdc(), VERTSIZE
);
1285 wxSize
wxDC::GetPPI() const
1287 int x
= ::GetDeviceCaps(GetHdc(), LOGPIXELSX
);
1288 int y
= ::GetDeviceCaps(GetHdc(), LOGPIXELSY
);
1290 return wxSize(x
, y
);
1293 // For use by wxWindows only, unless custom units are required.
1294 void wxDC::SetLogicalScale(double x
, double y
)
1296 m_logicalScaleX
= x
;
1297 m_logicalScaleY
= y
;
1300 #if WXWIN_COMPATIBILITY
1301 void wxDC::DoGetTextExtent(const wxString
& string
, float *x
, float *y
,
1302 float *descent
, float *externalLeading
,
1303 wxFont
*theFont
, bool use16bit
) const
1305 wxCoord x1
, y1
, descent1
, externalLeading1
;
1306 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1309 *descent
= descent1
;
1310 if (externalLeading
)
1311 *externalLeading
= externalLeading1
;
1315 // ---------------------------------------------------------------------------
1316 // spline drawing code
1317 // ---------------------------------------------------------------------------
1321 class wxSpline
: public wxObject
1327 wxSpline(wxList
*list
);
1328 void DeletePoints();
1330 // Doesn't delete points
1334 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
);
1336 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
1337 double a3
, double b3
, double a4
, double b4
);
1338 void wx_clear_stack();
1339 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
1340 double *y3
, double *x4
, double *y4
);
1341 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
1342 double x4
, double y4
);
1343 static bool wx_spline_add_point(double x
, double y
);
1344 static void wx_spline_draw_point_array(wxDC
*dc
);
1345 wxSpline
*wx_make_spline(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
);
1347 void wxDC::DoDrawSpline(wxList
*list
)
1349 wxSpline
spline(list
);
1351 wx_draw_open_spline(this, &spline
);
1354 wxList wx_spline_point_list
;
1356 void wx_draw_open_spline(wxDC
*dc
, wxSpline
*spline
)
1359 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
1360 double x1
, y1
, x2
, y2
;
1362 wxNode
*node
= spline
->points
->First();
1363 p
= (wxPoint
*)node
->Data();
1368 node
= node
->Next();
1369 p
= (wxPoint
*)node
->Data();
1373 cx1
= (double)((x1
+ x2
) / 2);
1374 cy1
= (double)((y1
+ y2
) / 2);
1375 cx2
= (double)((cx1
+ x2
) / 2);
1376 cy2
= (double)((cy1
+ y2
) / 2);
1378 wx_spline_add_point(x1
, y1
);
1380 while ((node
= node
->Next()) != NULL
)
1382 p
= (wxPoint
*)node
->Data();
1387 cx4
= (double)(x1
+ x2
) / 2;
1388 cy4
= (double)(y1
+ y2
) / 2;
1389 cx3
= (double)(x1
+ cx4
) / 2;
1390 cy3
= (double)(y1
+ cy4
) / 2;
1392 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
1396 cx2
= (double)(cx1
+ x2
) / 2;
1397 cy2
= (double)(cy1
+ y2
) / 2;
1400 wx_spline_add_point((double)wx_round(cx1
), (double)wx_round(cy1
));
1401 wx_spline_add_point(x2
, y2
);
1403 wx_spline_draw_point_array(dc
);
1407 /********************* CURVES FOR SPLINES *****************************
1409 The following spline drawing routine is from
1411 "An Algorithm for High-Speed Curve Generation"
1412 by George Merrill Chaikin,
1413 Computer Graphics and Image Processing, 3, Academic Press,
1418 "On Chaikin's Algorithm" by R. F. Riesenfeld,
1419 Computer Graphics and Image Processing, 4, Academic Press,
1422 ***********************************************************************/
1424 #define half(z1, z2) ((z1+z2)/2.0)
1427 /* iterative version */
1429 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
1432 register double xmid
, ymid
;
1433 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1436 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
1438 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
1439 xmid
= (double)half(x2
, x3
);
1440 ymid
= (double)half(y2
, y3
);
1441 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
1442 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
1443 wx_spline_add_point((double)wx_round(x1
), (double)wx_round(y1
));
1444 wx_spline_add_point((double)wx_round(xmid
), (double)wx_round(ymid
));
1446 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
1447 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
1448 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
1449 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
1455 /* utilities used by spline drawing routines */
1458 typedef struct wx_spline_stack_struct
{
1459 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
1463 #define SPLINE_STACK_DEPTH 20
1464 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
1465 static Stack
*wx_stack_top
;
1466 static int wx_stack_count
;
1468 void wx_clear_stack()
1470 wx_stack_top
= wx_spline_stack
;
1474 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
1476 wx_stack_top
->x1
= x1
;
1477 wx_stack_top
->y1
= y1
;
1478 wx_stack_top
->x2
= x2
;
1479 wx_stack_top
->y2
= y2
;
1480 wx_stack_top
->x3
= x3
;
1481 wx_stack_top
->y3
= y3
;
1482 wx_stack_top
->x4
= x4
;
1483 wx_stack_top
->y4
= y4
;
1488 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
1489 double *x3
, double *y3
, double *x4
, double *y4
)
1491 if (wx_stack_count
== 0)
1495 *x1
= wx_stack_top
->x1
;
1496 *y1
= wx_stack_top
->y1
;
1497 *x2
= wx_stack_top
->x2
;
1498 *y2
= wx_stack_top
->y2
;
1499 *x3
= wx_stack_top
->x3
;
1500 *y3
= wx_stack_top
->y3
;
1501 *x4
= wx_stack_top
->x4
;
1502 *y4
= wx_stack_top
->y4
;
1506 static bool wx_spline_add_point(double x
, double y
)
1508 wxPoint
*point
= new wxPoint
;
1511 wx_spline_point_list
.Append((wxObject
*)point
);
1515 static void wx_spline_draw_point_array(wxDC
*dc
)
1517 dc
->DrawLines(&wx_spline_point_list
, 0, 0);
1518 wxNode
*node
= wx_spline_point_list
.First();
1521 wxPoint
*point
= (wxPoint
*)node
->Data();
1524 node
= wx_spline_point_list
.First();
1528 wxSpline::wxSpline(wxList
*list
)
1533 wxSpline::~wxSpline()
1537 void wxSpline::DeletePoints()
1539 for(wxNode
*node
= points
->First(); node
; node
= points
->First())
1541 wxPoint
*point
= (wxPoint
*)node
->Data();
1549 #endif // wxUSE_SPLINES