// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-// ============================================================================
-// declarations
-// ============================================================================
-
-// ---------------------------------------------------------------------------
-// headers
-// ---------------------------------------------------------------------------
-
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#pragma hdrstop
#endif
+#if wxUSE_GRAPHICS_CONTEXT
+
#include "wx/graphics.h"
-#if wxUSE_GRAPHICS_CONTEXT
+#ifndef WX_PRECOMP
+ #include "wx/icon.h"
+ #include "wx/bitmap.h"
+ #include "wx/dcmemory.h"
+ #include "wx/region.h"
+#endif
+
+#if !defined(wxMAC_USE_CORE_GRAPHICS_BLEND_MODES)
+#define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
+#endif
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
-const double RAD2DEG = 180.0 / M_PI;
-const short kEmulatedMode = -1;
-const short kUnsupportedMode = -2;
+static const double RAD2DEG = 180.0 / M_PI;
//-----------------------------------------------------------------------------
// Local functions
//-----------------------------------------------------------------------------
-static inline double dmin(double a, double b)
-{
- return a < b ? a : b;
-}
-static inline double dmax(double a, double b)
-{
- return a > b ? a : b;
-}
-
static inline double DegToRad(double deg)
{
return (deg * M_PI) / 180.0;
}
-static inline double RadToDeg(double deg)
-{
- return (deg * 180.0) / M_PI;
-}
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_ABSTRACT_CLASS(wxGraphicsPath, wxObject)
wxPoint2DDouble wxGraphicsPath::GetCurrentPoint()
{
- wxDouble x,y ;
+ wxDouble x,y;
GetCurrentPoint(x,y);
return wxPoint2DDouble(x,y);
}
void wxGraphicsPath::AddQuadCurveToPoint( wxDouble cx, wxDouble cy, wxDouble x, wxDouble y )
{
// calculate using degree elevation to a cubic bezier
- wxPoint2DDouble c1 ;
- wxPoint2DDouble c2 ;
+ wxPoint2DDouble c1;
+ wxPoint2DDouble c2;
- wxPoint2DDouble start = GetCurrentPoint() ;
+ wxPoint2DDouble start = GetCurrentPoint();
wxPoint2DDouble end(x,y);
wxPoint2DDouble c(cx,cy);
- c1 = (1/3.0) * start + (2/3.0) * c;
- c2 = (2/3.0) * c + (1/3.0) * end ;
+ c1 = wxDouble(1/3.0) * start + wxDouble(2/3.0) * c;
+ c2 = wxDouble(2/3.0) * c + wxDouble(1/3.0) * end;
AddCurveToPoint(c1.m_x,c1.m_y,c2.m_x,c2.m_y,x,y);
}
wxPoint2DDouble p1(x1,y1);
wxPoint2DDouble p2(x2,y2);
- wxPoint2DDouble v1 = current - p1 ;
+ wxPoint2DDouble v1 = current - p1;
v1.Normalize();
- wxPoint2DDouble v2 = p2 - p1 ;
+ wxPoint2DDouble v2 = p2 - p1;
v2.Normalize();
wxDouble alpha = v1.GetVectorAngle() - v2.GetVectorAngle();
if ( alpha < 0 )
- alpha = 360 + alpha ;
+ alpha = 360 + alpha;
// TODO obtuse angles
alpha = DegToRad(alpha);
- wxDouble dist = r / sin(alpha/2) * cos(alpha/2) ;
+ wxDouble dist = r / sin(alpha/2) * cos(alpha/2);
// calculate tangential points
- wxPoint2DDouble t1 = dist*v1 + p1 ;
- wxPoint2DDouble t2 = dist*v2 + p1 ;
+ wxPoint2DDouble t1 = dist*v1 + p1;
+ wxPoint2DDouble t2 = dist*v2 + p1;
- wxPoint2DDouble nv1 = v1 ;
+ wxPoint2DDouble nv1 = v1;
nv1.SetVectorAngle(v1.GetVectorAngle()-90);
wxPoint2DDouble c = t1 + r*nv1;
- wxDouble a1 = v1.GetVectorAngle()+90 ;
- wxDouble a2 = v2.GetVectorAngle()-90 ;
+ wxDouble a1 = v1.GetVectorAngle()+90;
+ wxDouble a2 = v2.GetVectorAngle()-90;
AddLineToPoint(t1);
AddArc(c.m_x,c.m_y,r,DegToRad(a1),DegToRad(a2),true);
// wxGraphicsContext Convenience Methods
//-----------------------------------------------------------------------------
+IMPLEMENT_ABSTRACT_CLASS(wxGraphicsContext, wxObject)
+
void wxGraphicsContext::DrawPath( const wxGraphicsPath *path, int fillStyle )
{
FillPath( path , fillStyle );
void wxGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
{
- Translate(x,y) ;
+ Translate(x,y);
Rotate( -angle );
DrawText( str , 0, 0 );
Rotate( angle );
- Translate(-x,-y) ;
+ Translate(-x,-y);
}
void wxGraphicsContext::StrokeLine( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2)
{
wxGraphicsPath* path = CreatePath();
- path->MoveToPoint(x1, y1) ;
+ path->MoveToPoint(x1, y1);
path->AddLineToPoint( x2, y2 );
StrokePath( path );
delete path;
{
PushState();
Translate(x+w/2,y+h/2);
- wxDouble factor = ((wxDouble) w) / h ;
- Scale( factor , 1.0) ;
+ wxDouble factor = ((wxDouble) w) / h;
+ Scale( factor , 1.0);
path->AddCircle(0,0,h/2);
DrawPath(path);
PopState();
PushState();
Translate( x , y );
- double fw = w / radius;
- double fh = h / radius;
-
path->MoveToPoint(w, h / 2);
path->AddArcToPoint(w, h, w / 2, h, radius);
path->AddArcToPoint(0, h, 0, h / 2, radius);
{
wxASSERT(n > 1);
wxGraphicsPath* path = CreatePath();
- path->MoveToPoint(points[0].m_x, points[0].m_y) ;
- for ( int i = 1 ; i < n; ++i)
+ path->MoveToPoint(points[0].m_x, points[0].m_y);
+ for ( size_t i = 1; i < n; ++i)
path->AddLineToPoint( points[i].m_x, points[i].m_y );
StrokePath( path );
delete path;
{
wxASSERT(n > 1);
wxGraphicsPath* path = CreatePath();
- path->MoveToPoint(points[0].m_x, points[0].m_y) ;
- for ( int i = 1 ; i < n; ++i)
+ path->MoveToPoint(points[0].m_x, points[0].m_y);
+ for ( size_t i = 1; i < n; ++i)
path->AddLineToPoint( points[i].m_x, points[i].m_y );
DrawPath( path , fillStyle);
delete path;
{
wxASSERT(n > 0);
wxGraphicsPath* path = CreatePath();
- for ( int i = 0 ; i < n; ++i)
+ for ( size_t i = 0; i < n; ++i)
{
- path->MoveToPoint(beginPoints[i].m_x, beginPoints[i].m_y) ;
+ path->MoveToPoint(beginPoints[i].m_x, beginPoints[i].m_y);
path->AddLineToPoint( endPoints[i].m_x, endPoints[i].m_y );
}
StrokePath( path );
Init();
}
+void wxGCDC::SetGraphicsContext( wxGraphicsContext* ctx )
+{
+ delete m_graphicContext;
+ m_graphicContext = ctx;
+}
wxGCDC::wxGCDC(const wxWindowDC& dc)
{
m_ok = true;
if ( dc.GetFont().Ok())
m_graphicContext->SetFont(dc.GetFont());
+ if ( dc.GetPen().Ok())
+ m_graphicContext->SetPen(dc.GetPen());
+ if ( dc.GetBrush().Ok())
+ m_graphicContext->SetBrush(dc.GetBrush());
+ m_graphicContext->SetTextColor(dc.GetTextForeground());
}
void wxGCDC::Init()
delete m_graphicContext;
}
-void wxGCDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
+void wxGCDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool WXUNUSED(useMask) )
{
wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid DC") );
wxCHECK_RET( bmp.Ok(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid bitmap") );
void wxGCDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
{
- // TODO Clipping
-#if 0
wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoSetClippingRegion - invalid DC") );
wxCoord xx, yy, ww, hh;
ww = LogicalToDeviceXRel(width);
hh = LogicalToDeviceYRel(height);
- CGContextRef cgContext = ((wxCairoContext*)(m_graphicContext))->GetNativeContext();
- CGRect clipRect = CGRectMake( xx , yy , ww, hh );
- CGContextClipToRect( cgContext , clipRect );
-
- // SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh );
- // SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn );
-
+ m_graphicContext->Clip( xx, yy, ww, hh );
if ( m_clipping )
{
m_clipX1 = wxMax( m_clipX1, xx );
m_clipX2 = xx + ww;
m_clipY2 = yy + hh;
}
-
- // TODO: as soon as we don't reset the context for each operation anymore
- // we have to update the context as well
-#endif
-
}
void wxGCDC::DoSetClippingRegionAsRegion( const wxRegion ®ion )
}
else
{
-#if 0
- CopyRgn( (RgnHandle) region.GetWXHRGN() , (RgnHandle) m_macCurrentClipRgn );
- if ( xx != x || yy != y )
- OffsetRgn( (RgnHandle) m_macCurrentClipRgn , xx - x , yy - y );
- SectRgn( (RgnHandle)m_macCurrentClipRgn , (RgnHandle)m_macBoundaryClipRgn , (RgnHandle)m_macCurrentClipRgn );
-#endif
-
+ m_graphicContext->Clip( region );
if ( m_clipping )
{
m_clipX1 = wxMax( m_clipX1, xx );
void wxGCDC::DestroyClippingRegion()
{
- // TODO Clipping
-#if 0
- // CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn );
-
- CGContextRef cgContext = ((wxCairoContext*)(m_graphicContext))->GetNativeContext();
- CGContextRestoreGState( cgContext );
- CGContextSaveGState( cgContext );
-
+ m_graphicContext->ResetClip();
m_graphicContext->SetPen( m_pen );
m_graphicContext->SetBrush( m_brush );
m_clipping = false;
-#endif
-
}
void wxGCDC::DoGetSizeMM( int* width, int* height ) const
void wxGCDC::SetUserScale( double x, double y )
{
// allow negative ? -> no
+
m_userScaleX = x;
m_userScaleY = y;
ComputeScaleAndOrigin();
void wxGCDC::ComputeScaleAndOrigin()
{
- // this is a bit artificial, but we need to force wxGCDC to think
- // the pen has changed
- wxPen pen( GetPen() );
+ // CMB: copy scale to see if it changes
+ double origScaleX = m_scaleX;
+ double origScaleY = m_scaleY;
+ m_scaleX = m_logicalScaleX * m_userScaleX;
+ m_scaleY = m_logicalScaleY * m_userScaleY;
+ m_deviceOriginX = m_deviceOriginX + m_logicalOriginX;
+ m_deviceOriginY = m_deviceOriginY + m_logicalOriginY;
- m_pen = wxNullPen;
- SetPen( pen );
+ // CMB: if scale has changed call SetPen to recalulate the line width
+ if (m_scaleX != origScaleX || m_scaleY != origScaleY)
+ {
+ // this is a bit artificial, but we need to force wxDC to think
+ // the pen has changed
+ wxPen pen(GetPen());
+ m_pen = wxNullPen;
+ SetPen(pen);
+ SetFont(m_font);
+ }
}
-void wxGCDC::SetPalette( const wxPalette& palette )
-{}
+void wxGCDC::SetPalette( const wxPalette& WXUNUSED(palette) )
+{
+
+}
void wxGCDC::SetBackgroundMode( int mode )
{
{
m_font = font;
if ( m_graphicContext )
- m_graphicContext->SetFont( font );
+ {
+ wxFont f = font;
+ if ( f.Ok() )
+ f.SetPointSize( LogicalToDeviceYRel(font.GetPointSize()));
+ m_graphicContext->SetFont( f );
+ }
}
void wxGCDC::SetPen( const wxPen &pen )
}
-extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
- const wxColour & col, int style);
-
-bool wxGCDC::DoFloodFill(wxCoord x, wxCoord y,
- const wxColour& col, int style)
+bool wxGCDC::DoFloodFill(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
+ const wxColour& WXUNUSED(col), int WXUNUSED(style))
{
- // return wxDoFloodFill(this, x, y, col, style);
return false;
}
-bool wxGCDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
+bool wxGCDC::DoGetPixel( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxColour *WXUNUSED(col) ) const
{
// wxCHECK_MSG( 0 , false, wxT("wxGCDC(cg)::DoGetPixel - not implemented") );
return false;
wxGraphicsPath* path = m_graphicContext->CreatePath();
m_graphicContext->PushState();
m_graphicContext->Translate(xx+ww/2,yy+hh/2);
- wxDouble factor = ((wxDouble) ww) / hh ;
- m_graphicContext->Scale( factor , 1.0) ;
+ wxDouble factor = ((wxDouble) ww) / hh;
+ m_graphicContext->Scale( factor , 1.0);
if ( fill && (sa!=ea) )
path->MoveToPoint(0,0);
// since these angles (ea,sa) are measured counter-clockwise, we invert them to
return;
#endif
- wxPoint2DDouble* pointsD = new wxPoint2DDouble[n] ;
- for( int i = 0 ; i < n; ++i)
+ wxPoint2DDouble* pointsD = new wxPoint2DDouble[n];
+ for( int i = 0; i < n; ++i)
{
pointsD[i].m_x = LogicalToDeviceX(points[i].x + xoffset);
pointsD[i].m_y = LogicalToDeviceY(points[i].y + yoffset);
}
- m_graphicContext->StrokeLines( n , pointsD) ;
+ m_graphicContext->StrokeLines( n , pointsD);
delete[] pointsD;
}
m_graphicContext->StrokePath( path );
delete path;
}
-#endif
+#endif // wxUSE_SPLINES
void wxGCDC::DoDrawPolygon( int n, wxPoint points[],
wxCoord xoffset, wxCoord yoffset,
if ( m_logicalFunction != wxCOPY )
return;
- bool closeIt = false ;
+ bool closeIt = false;
if (points[n-1] != points[0])
- closeIt = true ;
+ closeIt = true;
- wxPoint2DDouble* pointsD = new wxPoint2DDouble[n+(closeIt?1:0)] ;
- for( int i = 0 ; i < n; ++i)
+ wxPoint2DDouble* pointsD = new wxPoint2DDouble[n+(closeIt?1:0)];
+ for( int i = 0; i < n; ++i)
{
pointsD[i].m_x = LogicalToDeviceX(points[i].x + xoffset);
pointsD[i].m_y = LogicalToDeviceY(points[i].y + yoffset);
if ( closeIt )
pointsD[n] = pointsD[0];
- m_graphicContext->DrawLines( n+(closeIt?1:0) , pointsD, fillStyle) ;
+ m_graphicContext->DrawLines( n+(closeIt?1:0) , pointsD, fillStyle);
delete[] pointsD;
}
wxASSERT(n > 1);
wxGraphicsPath* path = m_graphicContext->CreatePath();
- int i = 0 ;
- for ( int j = 0 ; j < n ; ++j)
+ int i = 0;
+ for ( int j = 0; j < n; ++j)
{
wxPoint start = points[i];
- path->MoveToPoint(LogicalToDeviceX(start.x+ xoffset), LogicalToDeviceY(start.y+ yoffset)) ;
+ path->MoveToPoint(LogicalToDeviceX(start.x+ xoffset), LogicalToDeviceY(start.y+ yoffset));
++i;
int l = count[j];
- for ( int k = 1 ; k < l ; ++k)
+ for ( int k = 1; k < l; ++k)
{
path->AddLineToPoint( LogicalToDeviceX(points[i].x+ xoffset), LogicalToDeviceY(points[i].y+ yoffset));
- ++i ;
+ ++i;
}
// close the polygon
if ( start != points[i-1])
if ( m_logicalFunction != wxCOPY )
return;
- wxCoord xx = LogicalToDeviceX(x);
- wxCoord yy = LogicalToDeviceY(y);
+ wxDouble xx = LogicalToDeviceX(x);
+ wxDouble yy = LogicalToDeviceY(y);
wxDouble ww = m_signX * LogicalToDeviceXRel(width);
- wxCoord hh = m_signY * LogicalToDeviceYRel(height);
+ wxDouble hh = m_signY * LogicalToDeviceYRel(height);
// CMB: draw nothing if transformed w or h is 0
if (ww == 0 || hh == 0)
bool wxGCDC::DoBlit(
wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
- wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
+ wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool WXUNUSED(useMask),
wxCoord xsrcMask, wxCoord ysrcMask )
{
wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid DC") );
wxCoord wwdest = LogicalToDeviceXRel(width);
wxCoord hhdest = LogicalToDeviceYRel(height);
- wxMemoryDC* memdc = dynamic_cast<wxMemoryDC*>(source);
+ wxMemoryDC* memdc = wxDynamicCast(source,wxMemoryDC);
if ( memdc && logical_func == wxCOPY )
{
-#if 0
- wxBitmap blit = memdc->GetSelectedObject();
+ wxBitmap blit = memdc->GetSelectedBitmap();
wxASSERT_MSG( blit.Ok() , wxT("Invalid bitmap for blitting") );
{
m_graphicContext->DrawBitmap( blit, xxdest , yydest , wwdest , hhdest );
}
-#endif
-
}
else
{
- wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") );
+ wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts, and only with wxCOPY logical operation.") );
return false;
}
{
wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoGetTextExtent - invalid DC") );
- wxFont formerFont = m_font;
if ( theFont )
{
m_graphicContext->SetFont( *theFont );
m_graphicContext->GetTextExtent( str, &w, &h, &d, &e );
if ( height )
- *height = DeviceToLogicalYRel( h );
+ *height = DeviceToLogicalYRel((wxCoord)h);
if ( descent )
- *descent =DeviceToLogicalYRel( d);
+ *descent = DeviceToLogicalYRel((wxCoord)d);
if ( externalLeading )
- *externalLeading = DeviceToLogicalYRel( e);
+ *externalLeading = DeviceToLogicalYRel((wxCoord)e);
if ( width )
- *width = DeviceToLogicalXRel( w );
+ *width = DeviceToLogicalXRel((wxCoord)w);
if ( theFont )
{
widths.Clear();
widths.Add(0,text.Length());
if ( text.IsEmpty() )
- return true ;
+ return true;
- wxArrayDouble widthsD ;
+ wxArrayDouble widthsD;
m_graphicContext->GetPartialTextExtents( text, widthsD );
for ( size_t i = 0; i < widths.GetCount(); ++i )
- widths[i] = DeviceToLogicalXRel( widthsD[i] + 0.5 ) ;
+ widths[i] = DeviceToLogicalXRel((wxCoord)(widthsD[i] + 0.5));
return true;
}
void wxGCDC::Clear(void)
{
wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::Clear - invalid DC") );
- // TODO
+ // TODO better implementation / incorporate size info into wxGCDC or context
+ m_graphicContext->SetBrush( m_backgroundBrush );
+ wxPen p = *wxTRANSPARENT_PEN;
+ m_graphicContext->SetPen( p );
+ DoDrawRectangle( 0, 0, 32000 , 32000 );
+ m_graphicContext->SetPen( m_pen );
+ m_graphicContext->SetBrush( m_brush );
}
void wxGCDC::DoGetSize(int *width, int *height) const
const wxColour& destColour,
wxDirection nDirection )
{
- wxPoint start ;
- wxPoint end ;
+ wxPoint start;
+ wxPoint end;
switch( nDirection)
{
case wxWEST :
start = rect.GetRightBottom();
start.x++;
end = rect.GetLeftBottom();
- break ;
+ break;
case wxEAST :
start = rect.GetLeftBottom();
end = rect.GetRightBottom();
end.x++;
- break ;
+ break;
case wxNORTH :
start = rect.GetLeftBottom();
start.y++;
end = rect.GetLeftTop();
- break ;
+ break;
case wxSOUTH :
start = rect.GetLeftTop();
end = rect.GetLeftBottom();
end.y++;
- break ;
+ break;
+ default :
+ break;
}
m_graphicContext->SetLinearGradientBrush(
LogicalToDeviceX(start.x),LogicalToDeviceY(start.y),
LogicalToDeviceX(end.x),LogicalToDeviceY(end.y), initialColour, destColour);
- wxCoord xx = LogicalToDeviceX(rect.x);
- wxCoord yy = LogicalToDeviceY(rect.y);
+ wxDouble xx = LogicalToDeviceX(rect.x);
+ wxDouble yy = LogicalToDeviceY(rect.y);
wxDouble ww = m_signX * LogicalToDeviceXRel(rect.width);
- wxCoord hh = m_signY * LogicalToDeviceYRel(rect.height);
+ wxDouble hh = m_signY * LogicalToDeviceYRel(rect.height);
if (ww == 0 || hh == 0)
return;
else
nRadius = cy;
- wxCoord xx = LogicalToDeviceX(rect.x);
- wxCoord yy = LogicalToDeviceY(rect.y);
+ wxDouble xx = LogicalToDeviceX(rect.x);
+ wxDouble yy = LogicalToDeviceY(rect.y);
wxDouble ww = m_signX * LogicalToDeviceXRel(rect.width);
- wxCoord hh = m_signY * LogicalToDeviceYRel(rect.height);
+ wxDouble hh = m_signY * LogicalToDeviceYRel(rect.height);
if (ww == 0 || hh == 0)
return;
}
m_graphicContext->SetPen(*wxTRANSPARENT_PEN);
- m_graphicContext->SetBrush( wxBrush( destColour) ) ;
+ m_graphicContext->SetBrush( wxBrush( destColour) );
m_graphicContext->DrawRectangle( xx,yy,ww,hh);
m_graphicContext->SetRadialGradientBrush(
wxDCBase::DoDrawCheckMark(x,y,width,height);
}
-#endif
-
+#endif // wxUSE_GRAPHICS_CONTEXT