]>
git.saurik.com Git - wxWidgets.git/blob - src/common/graphcmn.cpp
3cbc6cb3c4e0119a5447f439a186113014f303e4
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/graphcmn.cpp
3 // Purpose: graphics context methods common to all platforms
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
15 #if defined(__BORLANDC__)
19 #if wxUSE_GRAPHICS_CONTEXT
21 #include "wx/graphics.h"
25 #include "wx/bitmap.h"
26 #include "wx/dcmemory.h"
27 #include "wx/region.h"
31 #if !defined(wxMAC_USE_CORE_GRAPHICS_BLEND_MODES)
32 #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
35 //-----------------------------------------------------------------------------
37 //-----------------------------------------------------------------------------
39 static const double RAD2DEG
= 180.0 / M_PI
;
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
45 static inline double DegToRad(double deg
)
47 return (deg
* M_PI
) / 180.0;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 IMPLEMENT_DYNAMIC_CLASS(wxGraphicsObject
, wxObject
)
58 wxGraphicsObjectRefData::wxGraphicsObjectRefData( wxGraphicsRenderer
* renderer
)
60 m_renderer
= renderer
;
62 wxGraphicsObjectRefData::wxGraphicsObjectRefData( const wxGraphicsObjectRefData
* data
)
64 m_renderer
= data
->m_renderer
;
66 wxGraphicsRenderer
* wxGraphicsObjectRefData::GetRenderer() const
71 wxGraphicsObjectRefData
* wxGraphicsObjectRefData::Clone() const
73 return new wxGraphicsObjectRefData(this);
76 wxGraphicsObject::wxGraphicsObject()
80 wxGraphicsObject::wxGraphicsObject( wxGraphicsRenderer
* renderer
)
82 SetRefData( new wxGraphicsObjectRefData(renderer
));
85 wxGraphicsObject::~wxGraphicsObject()
89 bool wxGraphicsObject::IsNull() const
91 return m_refData
== NULL
;
94 wxGraphicsRenderer
* wxGraphicsObject::GetRenderer() const
96 return ( IsNull() ? NULL
: GetGraphicsData()->GetRenderer() );
99 wxGraphicsObjectRefData
* wxGraphicsObject::GetGraphicsData() const
101 return (wxGraphicsObjectRefData
*) m_refData
;
104 wxObjectRefData
* wxGraphicsObject::CreateRefData() const
106 wxLogDebug(wxT("A Null Object cannot be changed"));
110 wxObjectRefData
* wxGraphicsObject::CloneRefData(const wxObjectRefData
* data
) const
112 const wxGraphicsObjectRefData
* ptr
= (const wxGraphicsObjectRefData
*) data
;
116 //-----------------------------------------------------------------------------
118 //-----------------------------------------------------------------------------
120 IMPLEMENT_DYNAMIC_CLASS(wxGraphicsPen
, wxGraphicsObject
)
121 IMPLEMENT_DYNAMIC_CLASS(wxGraphicsBrush
, wxGraphicsObject
)
122 IMPLEMENT_DYNAMIC_CLASS(wxGraphicsFont
, wxGraphicsObject
)
123 WXDLLIMPEXP_DATA_CORE(wxGraphicsPen
) wxNullGraphicsPen
;
124 WXDLLIMPEXP_DATA_CORE(wxGraphicsBrush
) wxNullGraphicsBrush
;
125 WXDLLIMPEXP_DATA_CORE(wxGraphicsFont
) wxNullGraphicsFont
;
127 IMPLEMENT_ABSTRACT_CLASS(wxGraphicsRenderer
, wxObject
)
128 IMPLEMENT_ABSTRACT_CLASS(wxGraphicsMatrix
, wxGraphicsObject
)
129 IMPLEMENT_ABSTRACT_CLASS(wxGraphicsPath
, wxGraphicsObject
)
131 wxPoint2DDouble
wxGraphicsPath::GetCurrentPoint()
134 GetCurrentPoint(x
,y
);
135 return wxPoint2DDouble(x
,y
);
138 void wxGraphicsPath::MoveToPoint( const wxPoint2DDouble
& p
)
140 MoveToPoint( p
.m_x
, p
.m_y
);
143 void wxGraphicsPath::AddLineToPoint( const wxPoint2DDouble
& p
)
145 AddLineToPoint( p
.m_x
, p
.m_y
);
148 void wxGraphicsPath::AddCurveToPoint( const wxPoint2DDouble
& c1
, const wxPoint2DDouble
& c2
, const wxPoint2DDouble
& e
)
150 AddCurveToPoint(c1
.m_x
, c1
.m_y
, c2
.m_x
, c2
.m_y
, e
.m_x
, e
.m_y
);
153 void wxGraphicsPath::AddArc( const wxPoint2DDouble
& c
, wxDouble r
, wxDouble startAngle
, wxDouble endAngle
, bool clockwise
)
155 AddArc(c
.m_x
, c
.m_y
, r
, startAngle
, endAngle
, clockwise
);
158 wxRect2DDouble
wxGraphicsPath::GetBox()
162 return wxRect2DDouble( x
,y
,w
,h
);
165 bool wxGraphicsPath::Contains( const wxPoint2DDouble
& c
, int fillStyle
)
167 return Contains( c
.m_x
, c
.m_y
, fillStyle
);
174 void wxGraphicsPath::AddQuadCurveToPoint( wxDouble cx
, wxDouble cy
, wxDouble x
, wxDouble y
)
176 // calculate using degree elevation to a cubic bezier
180 wxPoint2DDouble start
= GetCurrentPoint();
181 wxPoint2DDouble
end(x
,y
);
182 wxPoint2DDouble
c(cx
,cy
);
183 c1
= wxDouble(1/3.0) * start
+ wxDouble(2/3.0) * c
;
184 c2
= wxDouble(2/3.0) * c
+ wxDouble(1/3.0) * end
;
185 AddCurveToPoint(c1
.m_x
,c1
.m_y
,c2
.m_x
,c2
.m_y
,x
,y
);
188 void wxGraphicsPath::AddRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
191 AddLineToPoint(x
,y
+h
);
192 AddLineToPoint(x
+w
,y
+h
);
193 AddLineToPoint(x
+w
,y
);
197 void wxGraphicsPath::AddCircle( wxDouble x
, wxDouble y
, wxDouble r
)
200 AddArc( x
,y
,r
,0,2*M_PI
,false);
204 void wxGraphicsPath::AddEllipse( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
208 wxDouble xc
= x
+ rw
;
209 wxDouble yc
= y
+ rh
;
210 wxGraphicsMatrix
* m
= GetRenderer()->CreateMatrix();
213 wxGraphicsPath
* p
= GetRenderer()->CreatePath();
214 p
->AddCircle(0,0,rh
);
221 void wxGraphicsPath::AddRoundedRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
, wxDouble radius
)
224 AddRectangle(x
,y
,w
,h
);
227 MoveToPoint( x
+ w
, y
+ h
/ 2);
228 AddArcToPoint(x
+ w
, y
+ h
, x
+ w
/ 2, y
+ h
, radius
);
229 AddArcToPoint(x
, y
+ h
, x
, y
+ h
/ 2, radius
);
230 AddArcToPoint(x
, y
, x
+ w
/ 2, y
, radius
);
231 AddArcToPoint(x
+ w
, y
, x
+ w
, y
+ h
/ 2, radius
);
236 // draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
237 void wxGraphicsPath::AddArcToPoint( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
, wxDouble r
)
239 wxPoint2DDouble current
= GetCurrentPoint();
240 wxPoint2DDouble
p1(x1
,y1
);
241 wxPoint2DDouble
p2(x2
,y2
);
243 wxPoint2DDouble v1
= current
- p1
;
245 wxPoint2DDouble v2
= p2
- p1
;
248 wxDouble alpha
= v1
.GetVectorAngle() - v2
.GetVectorAngle();
252 // TODO obtuse angles
254 alpha
= DegToRad(alpha
);
256 wxDouble dist
= r
/ sin(alpha
/2) * cos(alpha
/2);
257 // calculate tangential points
258 wxPoint2DDouble t1
= dist
*v1
+ p1
;
259 wxPoint2DDouble t2
= dist
*v2
+ p1
;
261 wxPoint2DDouble nv1
= v1
;
262 nv1
.SetVectorAngle(v1
.GetVectorAngle()-90);
263 wxPoint2DDouble c
= t1
+ r
*nv1
;
265 wxDouble a1
= v1
.GetVectorAngle()+90;
266 wxDouble a2
= v2
.GetVectorAngle()-90;
269 AddArc(c
.m_x
,c
.m_y
,r
,DegToRad(a1
),DegToRad(a2
),true);
273 //-----------------------------------------------------------------------------
274 // wxGraphicsContext Convenience Methods
275 //-----------------------------------------------------------------------------
277 IMPLEMENT_ABSTRACT_CLASS(wxGraphicsContext
, wxObject
)
280 wxGraphicsContext::wxGraphicsContext(wxGraphicsRenderer
* renderer
) : wxGraphicsObject(renderer
)
284 wxGraphicsContext::~wxGraphicsContext()
289 void wxGraphicsContext::SetPen( const wxGraphicsPen
& pen
)
294 void wxGraphicsContext::SetPen( const wxPen
& pen
)
296 if ( pen
.GetStyle() == wxTRANSPARENT
)
297 SetPen( wxNullGraphicsPen
);
299 SetPen( CreatePen( pen
) );
302 // sets the brush for filling
303 void wxGraphicsContext::SetBrush( const wxGraphicsBrush
& brush
)
308 void wxGraphicsContext::SetBrush( const wxBrush
& brush
)
310 if ( brush
.GetStyle() == wxTRANSPARENT
)
311 SetBrush( wxNullGraphicsBrush
);
313 SetBrush( CreateBrush( brush
) );
316 // sets the brush for filling
317 void wxGraphicsContext::SetFont( const wxGraphicsFont
& font
)
322 void wxGraphicsContext::SetFont( const wxFont
& font
, const wxColour
& colour
)
325 SetFont( CreateFont( font
, colour
) );
327 SetFont( wxNullGraphicsFont
);
330 void wxGraphicsContext::DrawPath( const wxGraphicsPath
*path
, int fillStyle
)
332 FillPath( path
, fillStyle
);
336 void wxGraphicsContext::DrawText( const wxString
&str
, wxDouble x
, wxDouble y
, wxDouble angle
)
340 DrawText( str
, 0, 0 );
345 void wxGraphicsContext::StrokeLine( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
)
347 wxGraphicsPath
* path
= CreatePath();
348 path
->MoveToPoint(x1
, y1
);
349 path
->AddLineToPoint( x2
, y2
);
354 void wxGraphicsContext::DrawRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
356 wxGraphicsPath
* path
= CreatePath();
357 path
->AddRectangle( x
, y
, w
, h
);
362 void wxGraphicsContext::DrawEllipse( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
)
364 wxGraphicsPath
* path
= CreatePath();
365 path
->AddEllipse(x
,y
,w
,h
);
370 void wxGraphicsContext::DrawRoundedRectangle( wxDouble x
, wxDouble y
, wxDouble w
, wxDouble h
, wxDouble radius
)
372 wxGraphicsPath
* path
= CreatePath();
373 path
->AddRoundedRectangle(x
,y
,w
,h
,radius
);
378 void wxGraphicsContext::StrokeLines( size_t n
, const wxPoint2DDouble
*points
)
381 wxGraphicsPath
* path
= CreatePath();
382 path
->MoveToPoint(points
[0].m_x
, points
[0].m_y
);
383 for ( size_t i
= 1; i
< n
; ++i
)
384 path
->AddLineToPoint( points
[i
].m_x
, points
[i
].m_y
);
389 void wxGraphicsContext::DrawLines( size_t n
, const wxPoint2DDouble
*points
, int fillStyle
)
392 wxGraphicsPath
* path
= CreatePath();
393 path
->MoveToPoint(points
[0].m_x
, points
[0].m_y
);
394 for ( size_t i
= 1; i
< n
; ++i
)
395 path
->AddLineToPoint( points
[i
].m_x
, points
[i
].m_y
);
396 DrawPath( path
, fillStyle
);
400 void wxGraphicsContext::StrokeLines( size_t n
, const wxPoint2DDouble
*beginPoints
, const wxPoint2DDouble
*endPoints
)
403 wxGraphicsPath
* path
= CreatePath();
404 for ( size_t i
= 0; i
< n
; ++i
)
406 path
->MoveToPoint(beginPoints
[i
].m_x
, beginPoints
[i
].m_y
);
407 path
->AddLineToPoint( endPoints
[i
].m_x
, endPoints
[i
].m_y
);
413 // create a 'native' matrix corresponding to these values
414 wxGraphicsMatrix
* wxGraphicsContext::CreateMatrix( wxDouble a
, wxDouble b
, wxDouble c
, wxDouble d
,
415 wxDouble tx
, wxDouble ty
)
417 return GetRenderer()->CreateMatrix(a
,b
,c
,d
,tx
,ty
);
420 wxGraphicsPath
* wxGraphicsContext::CreatePath()
422 return GetRenderer()->CreatePath();
425 wxGraphicsPen
wxGraphicsContext::CreatePen(const wxPen
& pen
)
427 return GetRenderer()->CreatePen(pen
);
430 wxGraphicsBrush
wxGraphicsContext::CreateBrush(const wxBrush
& brush
)
432 return GetRenderer()->CreateBrush(brush
);
435 // sets the brush to a linear gradient, starting at (x1,y1) with color c1 to (x2,y2) with color c2
436 wxGraphicsBrush
wxGraphicsContext::CreateLinearGradientBrush( wxDouble x1
, wxDouble y1
, wxDouble x2
, wxDouble y2
,
437 const wxColour
&c1
, const wxColour
&c2
)
439 return GetRenderer()->CreateLinearGradientBrush(x1
,y1
,x2
,y2
,c1
,c2
);
442 // sets the brush to a radial gradient originating at (xo,yc) with color oColor and ends on a circle around (xc,yc)
443 // with radius r and color cColor
444 wxGraphicsBrush
wxGraphicsContext::CreateRadialGradientBrush( wxDouble xo
, wxDouble yo
, wxDouble xc
, wxDouble yc
, wxDouble radius
,
445 const wxColour
&oColor
, const wxColour
&cColor
)
447 return GetRenderer()->CreateRadialGradientBrush(xo
,yo
,xc
,yc
,radius
,oColor
,cColor
);
451 wxGraphicsFont
wxGraphicsContext::CreateFont( const wxFont
&font
, const wxColour
&col
)
453 return GetRenderer()->CreateFont(font
,col
);
456 wxGraphicsContext
* wxGraphicsContext::Create( const wxWindowDC
& dc
)
458 return wxGraphicsRenderer::GetDefaultRenderer()->CreateContext(dc
);
461 wxGraphicsContext
* wxGraphicsContext::CreateFromNative( void * context
)
463 return wxGraphicsRenderer::GetDefaultRenderer()->CreateContextFromNativeContext(context
);
466 wxGraphicsContext
* wxGraphicsContext::CreateFromNativeWindow( void * window
)
468 return wxGraphicsRenderer::GetDefaultRenderer()->CreateContextFromNativeWindow(window
);
471 wxGraphicsContext
* wxGraphicsContext::Create( wxWindow
* window
)
473 return wxGraphicsRenderer::GetDefaultRenderer()->CreateContext(window
);
476 #endif // wxUSE_GRAPHICS_CONTEXT