#include "wx/wxprec.h"
-#include "wx/dc.h"
-
#ifdef __BORLANDC__
-#pragma hdrstop
+ #pragma hdrstop
#endif
+#include "wx/dc.h"
+
#if wxUSE_GRAPHICS_CONTEXT
#ifndef WX_PRECOMP
#include "wx/msw/wrapcdlg.h"
#include "wx/image.h"
#include "wx/window.h"
- #include "wx/dc.h"
#include "wx/utils.h"
#include "wx/dialog.h"
#include "wx/app.h"
#include "wx/bitmap.h"
- #include "wx/dcmemory.h"
#include "wx/log.h"
#include "wx/icon.h"
- #include "wx/dcprint.h"
#include "wx/module.h"
+ // include all dc types that are used as a param
+ #include "wx/dc.h"
+ #include "wx/dcclient.h"
+ #include "wx/dcmemory.h"
+ #include "wx/dcprint.h"
#endif
#include "wx/private/graphics.h"
// gets the bounding box enclosing all points (possibly including control points)
virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const;
- virtual bool Contains( wxDouble x, wxDouble y, int fillStyle = wxODDEVEN_RULE) const;
+ virtual bool Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle = wxODDEVEN_RULE) const;
private :
GraphicsPath* m_path;
class wxGDIPlusContext : public wxGraphicsContext
{
public:
- wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc );
+ wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc , wxDouble width, wxDouble height );
wxGDIPlusContext( wxGraphicsRenderer* renderer, HWND hwnd );
wxGDIPlusContext( wxGraphicsRenderer* renderer, Graphics* gr);
wxGDIPlusContext();
virtual void * GetNativeContext();
virtual void StrokePath( const wxGraphicsPath& p );
- virtual void FillPath( const wxGraphicsPath& p , int fillStyle = wxODDEVEN_RULE );
+ virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
// stroke lines connecting each of the points
virtual void StrokeLines( size_t n, const wxPoint2DDouble *points);
// draws a polygon
- virtual void DrawLines( size_t n, const wxPoint2DDouble *points, int fillStyle = wxODDEVEN_RULE );
+ virtual void DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
+ virtual bool SetAntialiasMode(wxAntialiasMode antialias);
+
+ virtual bool SetCompositionMode(wxCompositionMode op);
+
+ virtual void BeginLayer(wxDouble opacity);
+
+ virtual void EndLayer();
+
virtual void Translate( wxDouble dx , wxDouble dy );
virtual void Scale( wxDouble xScale , wxDouble yScale );
virtual void Rotate( wxDouble angle );
virtual void PushState();
virtual void PopState();
- virtual void DrawText( const wxString &str, wxDouble x, wxDouble y);
virtual void GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
wxDouble *descent, wxDouble *externalLeading ) const;
virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
virtual bool ShouldOffset() const;
+ virtual void GetSize( wxDouble* width, wxDouble *height );
private:
void Init();
void SetDefaults();
+ virtual void DoDrawText(const wxString& str, wxDouble x, wxDouble y)
+ { DoDrawFilledText(str, x, y, wxNullGraphicsBrush); }
+ virtual void DoDrawFilledText(const wxString& str, wxDouble x, wxDouble y,
+ const wxGraphicsBrush& backgroundBrush);
+
Graphics* m_context;
GraphicsStates m_stateStack;
GraphicsState m_state1;
GraphicsState m_state2;
+ wxDouble m_width;
+ wxDouble m_height;
+
DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusContext)
};
-class WXDLLIMPEXP_CORE wxGDIPlusMeasuringContext : public wxGDIPlusContext
+class wxGDIPlusMeasuringContext : public wxGDIPlusContext
{
public:
- wxGDIPlusMeasuringContext( wxGraphicsRenderer* renderer ) : wxGDIPlusContext( renderer , m_hdc = GetDC(NULL) )
+ wxGDIPlusMeasuringContext( wxGraphicsRenderer* renderer ) : wxGDIPlusContext( renderer , m_hdc = GetDC(NULL), 1000, 1000 )
{
}
wxGDIPlusMeasuringContext()
m_helper = NULL;
}
-wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer,
+wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer,
const wxBitmap &bmp) : wxGraphicsObjectRefData( renderer )
{
m_bitmap = NULL;
*h = bounds.Height;
}
-bool wxGDIPlusPathData::Contains( wxDouble x, wxDouble y, int fillStyle ) const
+bool wxGDIPlusPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle ) const
{
m_path->SetFillMode( fillStyle == wxODDEVEN_RULE ? FillModeAlternate : FillModeWinding);
return m_path->IsVisible( (FLOAT) x,(FLOAT) y) == TRUE ;
bool m_offset;
} ;
-wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc )
+wxGDIPlusContext::wxGDIPlusContext( wxGraphicsRenderer* renderer, HDC hdc, wxDouble width, wxDouble height )
: wxGraphicsContext(renderer)
{
Init();
m_context = new Graphics( hdc);
+ m_width = width;
+ m_height = height;
SetDefaults();
}
{
Init();
m_context = new Graphics( hwnd);
+ RECT rect = wxGetWindowRect(hwnd);
+ m_width = rect.right - rect.left;
+ m_height = rect.bottom - rect.top;
SetDefaults();
}
m_context = NULL;
m_state1 = 0;
m_state2= 0;
+ m_height = 0;
+ m_width = 0;
}
void wxGDIPlusContext::SetDefaults()
void wxGDIPlusContext::StrokeLines( size_t n, const wxPoint2DDouble *points)
{
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
if ( !m_pen.IsNull() )
{
wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
}
}
-void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, int WXUNUSED(fillStyle) )
+void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode WXUNUSED(fillStyle) )
{
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
Point *cpoints = new Point[n];
for (size_t i = 0; i < n; i++)
void wxGDIPlusContext::StrokePath( const wxGraphicsPath& path )
{
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
if ( !m_pen.IsNull() )
{
wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
}
}
-void wxGDIPlusContext::FillPath( const wxGraphicsPath& path , int fillStyle )
+void wxGDIPlusContext::FillPath( const wxGraphicsPath& path , wxPolygonFillMode fillStyle )
{
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
if ( !m_brush.IsNull() )
{
wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
}
}
+bool wxGDIPlusContext::SetAntialiasMode(wxAntialiasMode antialias)
+{
+ if (m_antialias == antialias)
+ return true;
+
+ m_antialias = antialias;
+
+ SmoothingMode antialiasMode;
+ switch (antialias)
+ {
+ case wxANTIALIAS_DEFAULT:
+ antialiasMode = SmoothingModeHighQuality;
+ break;
+ case wxANTIALIAS_NONE:
+ antialiasMode = SmoothingModeNone;
+ break;
+ default:
+ return false;
+ }
+ m_context->SetSmoothingMode(antialiasMode);
+ return true;
+}
+
+bool wxGDIPlusContext::SetCompositionMode(wxCompositionMode op)
+{
+ if ( m_composition == op )
+ return true;
+
+ m_composition = op;
+
+ if (m_composition == wxCOMPOSITION_DEST)
+ return true;
+
+ CompositingMode cop;
+ switch (op)
+ {
+ case wxCOMPOSITION_SOURCE:
+ cop = CompositingModeSourceCopy;
+ break;
+ case wxCOMPOSITION_OVER:
+ cop = CompositingModeSourceOver;
+ break;
+ default:
+ return false;
+ }
+
+ m_context->SetCompositingMode(cop);
+ return true;
+}
+
+void wxGDIPlusContext::BeginLayer(wxDouble /* opacity */)
+{
+ // TODO
+}
+
+void wxGDIPlusContext::EndLayer()
+{
+ // TODO
+}
+
void wxGDIPlusContext::Rotate( wxDouble angle )
{
m_context->RotateTransform( RadToDeg(angle) );
void wxGDIPlusContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
{
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
Bitmap* image = static_cast<wxGDIPlusBitmapData*>(bmp.GetRefData())->GetGDIPlusBitmap();
if ( image )
{
void wxGDIPlusContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
{
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
// the built-in conversion fails when there is alpha in the HICON (eg XP style icons), we can only
// find out by looking at the bitmap data whether there really was alpha in it
HICON hIcon = (HICON)icon.GetHICON();
interim.LockBits(&bounds, ImageLockModeRead,
interim.GetPixelFormat(),&data);
-
+
bool hasAlpha = false;
for ( size_t y = 0 ; y < height && !hasAlpha ; ++y)
{
DeleteObject(iconInfo.hbmMask);
}
-void wxGDIPlusContext::DrawText( const wxString &str, wxDouble x, wxDouble y )
+void wxGDIPlusContext::DoDrawFilledText(const wxString& str,
+ wxDouble x, wxDouble y,
+ const wxGraphicsBrush& brush)
{
- if ( m_font.IsNull() || str.IsEmpty())
+ if (m_composition == wxCOMPOSITION_DEST)
+ return;
+
+ wxCHECK_RET( !m_font.IsNull(),
+ wxT("wxGDIPlusContext::DrawText - no valid font set") );
+
+ if ( str.IsEmpty())
return ;
- wxWCharBuffer s = str.wc_str( *wxConvUI );
- m_context->DrawString( s , -1 , ((wxGDIPlusFontData*)m_font.GetRefData())->GetGDIPlusFont() ,
- PointF( x , y ) , StringFormat::GenericTypographic() , ((wxGDIPlusFontData*)m_font.GetRefData())->GetGDIPlusBrush() );
+ wxGDIPlusFontData * const
+ fontData = (wxGDIPlusFontData *)m_font.GetRefData();
+ wxGDIPlusBrushData * const
+ brushData = (wxGDIPlusBrushData *)brush.GetRefData();
+
+ m_context->DrawString
+ (
+ str.wc_str(*wxConvUI), // string to draw, always Unicode
+ -1, // length: string is NUL-terminated
+ fontData->GetGDIPlusFont(),
+ PointF(x, y),
+ StringFormat::GenericTypographic(),
+ brushData ? brushData->GetGDIPlusBrush()
+ : fontData->GetGDIPlusBrush()
+ );
}
void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height,
wxDouble *descent, wxDouble *externalLeading ) const
{
+ wxCHECK_RET( !m_font.IsNull(), wxT("wxGDIPlusContext::GetTextExtent - no valid font set") );
+
wxWCharBuffer s = str.wc_str( *wxConvUI );
FontFamily ffamily ;
Font* f = ((wxGDIPlusFontData*)m_font.GetRefData())->GetGDIPlusFont();
{
RectF layoutRect(0,0, 100000.0f, 100000.0f);
StringFormat strFormat( StringFormat::GenericTypographic() );
- strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() );
+ strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() );
RectF bounds ;
m_context->MeasureString((const wchar_t *) s , wcslen(s) , f, layoutRect, &strFormat, &bounds ) ;
widths.Empty();
widths.Add(0, text.length());
+ wxCHECK_RET( !m_font.IsNull(), wxT("wxGDIPlusContext::GetPartialTextExtents - no valid font set") );
+
if (text.empty())
return;
ranges[i].Length = 1 ;
}
strFormat.SetMeasurableCharacterRanges(len,ranges);
- strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() );
+ strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() );
m_context->MeasureCharacterRanges(ws, -1 , f,layoutRect, &strFormat,1,regions) ;
RectF bbox ;
}
bool wxGDIPlusContext::ShouldOffset() const
-{
+{
int penwidth = 0 ;
if ( !m_pen.IsNull() )
{
m_context->GetTransform((Matrix*) matrix.GetNativeMatrix());
return matrix;
}
+
+void wxGDIPlusContext::GetSize( wxDouble* width, wxDouble *height )
+{
+ *width = m_width;
+ *height = m_height;
+}
//-----------------------------------------------------------------------------
// wxGDIPlusRenderer declaration
//-----------------------------------------------------------------------------
public :
wxGDIPlusRenderer()
{
- m_loaded = false;
+ m_loaded = -1;
m_gditoken = 0;
}
virtual ~wxGDIPlusRenderer()
{
- if (m_loaded)
+ if ( m_loaded == 1 )
{
Unload();
}
virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc);
virtual wxGraphicsContext * CreateContext( const wxPrinterDC& dc);
-
+
virtual wxGraphicsContext * CreateContextFromNativeContext( void * context );
virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
// create a native bitmap representation
virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap );
-
+
// create a subimage from a native image representation
virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
protected :
- void EnsureIsLoaded();
+ bool EnsureIsLoaded();
void Load();
void Unload();
friend class wxGDIPlusRendererModule;
private :
- bool m_loaded;
+ int m_loaded;
ULONG_PTR m_gditoken;
DECLARE_DYNAMIC_CLASS_NO_COPY(wxGDIPlusRenderer)
return &gs_GDIPlusRenderer;
}
-void wxGDIPlusRenderer::EnsureIsLoaded()
+bool wxGDIPlusRenderer::EnsureIsLoaded()
{
- if (!m_loaded)
+ // load gdiplus.dll if not yet loaded, but don't bother doing it again
+ // if we already tried and failed (we don't want to spend lot of time
+ // returning NULL from wxGraphicsContext::Create(), which may be called
+ // relatively frequently):
+ if ( m_loaded == -1 )
{
Load();
}
+
+ return m_loaded == 1;
}
+// call EnsureIsLoaded() and return returnOnFail value if it fails
+#define ENSURE_LOADED_OR_RETURN(returnOnFail) \
+ if ( !EnsureIsLoaded() ) \
+ return (returnOnFail)
+
+
void wxGDIPlusRenderer::Load()
{
GdiplusStartupInput input;
GdiplusStartupOutput output;
- GdiplusStartup(&m_gditoken,&input,&output);
- m_loaded = true;
+ if ( GdiplusStartup(&m_gditoken,&input,&output) == Gdiplus::Ok )
+ {
+ wxLogTrace("gdiplus", "successfully initialized GDI+");
+ m_loaded = 1;
+ }
+ else
+ {
+ wxLogTrace("gdiplus", "failed to initialize GDI+, missing gdiplus.dll?");
+ m_loaded = 0;
+ }
}
void wxGDIPlusRenderer::Unload()
GdiplusShutdown(m_gditoken);
m_gditoken = NULL;
}
- m_loaded = false;
+ m_loaded = -1; // next Load() will try again
}
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxWindowDC& dc)
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(NULL);
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
- return new wxGDIPlusContext(this,(HDC) msw->GetHDC());
+ wxSize sz = dc.GetSize();
+ return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
}
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxPrinterDC& dc)
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(NULL);
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
- return new wxGDIPlusContext(this,(HDC) msw->GetHDC());
+ wxSize sz = dc.GetSize();
+ return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
}
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc)
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(NULL);
wxMSWDCImpl *msw = wxDynamicCast( dc.GetImpl() , wxMSWDCImpl );
- return new wxGDIPlusContext(this,(HDC) msw->GetHDC());
+ wxSize sz = dc.GetSize();
+ return new wxGDIPlusContext(this,(HDC) msw->GetHDC(), sz.x, sz.y);
}
wxGraphicsContext * wxGDIPlusRenderer::CreateMeasuringContext()
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(NULL);
return new wxGDIPlusMeasuringContext(this);
}
wxGraphicsContext * wxGDIPlusRenderer::CreateContextFromNativeContext( void * context )
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(NULL);
return new wxGDIPlusContext(this,(Graphics*) context);
}
wxGraphicsContext * wxGDIPlusRenderer::CreateContextFromNativeWindow( void * window )
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(NULL);
return new wxGDIPlusContext(this,(HWND) window);
}
wxGraphicsContext * wxGDIPlusRenderer::CreateContext( wxWindow* window )
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(NULL);
return new wxGDIPlusContext(this, (HWND) window->GetHWND() );
}
wxGraphicsPath wxGDIPlusRenderer::CreatePath()
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsPath);
wxGraphicsPath m;
m.SetRefData( new wxGDIPlusPathData(this));
return m;
wxDouble tx, wxDouble ty)
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsMatrix);
wxGraphicsMatrix m;
wxGDIPlusMatrixData* data = new wxGDIPlusMatrixData( this );
data->Set( a,b,c,d,tx,ty ) ;
wxGraphicsPen wxGDIPlusRenderer::CreatePen(const wxPen& pen)
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsPen);
if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
return wxNullGraphicsPen;
else
wxGraphicsBrush wxGDIPlusRenderer::CreateBrush(const wxBrush& brush )
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
return wxNullGraphicsBrush;
else
wxGraphicsBrush wxGDIPlusRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
const wxColour&c1, const wxColour&c2)
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
wxGraphicsBrush p;
wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this );
d->CreateLinearGradientBrush(x1, y1, x2, y2, c1, c2);
wxGraphicsBrush wxGDIPlusRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
const wxColour &oColor, const wxColour &cColor)
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
wxGraphicsBrush p;
wxGDIPlusBrushData* d = new wxGDIPlusBrushData( this );
d->CreateRadialGradientBrush(xo,yo,xc,yc,radius,oColor,cColor);
// sets the font
wxGraphicsFont wxGDIPlusRenderer::CreateFont( const wxFont &font , const wxColour &col )
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont);
if ( font.Ok() )
{
wxGraphicsFont p;
wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmap( const wxBitmap &bitmap )
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
if ( bitmap.Ok() )
{
wxGraphicsBitmap p;
wxGraphicsBitmap wxGDIPlusRenderer::CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
{
- EnsureIsLoaded();
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
Bitmap* image = static_cast<wxGDIPlusBitmapData*>(bitmap.GetRefData())->GetGDIPlusBitmap();
if ( image )
{