#if wxUSE_CAIRO
+// keep cairo.h from defining dllimport as we're defining the symbols inside
+// the wx dll in order to load them dynamically.
+#define cairo_public
+
#include "wx/cairo.h"
#ifndef WX_PRECOMP
#include "wx/dcclient.h"
#include "wx/dcmemory.h"
#include "wx/dcprint.h"
+ #ifdef __WXGTK__
+ #include "wx/window.h"
+ #endif
#endif
#include "wx/private/graphics.h"
cairo_font_slant_t m_slant;
cairo_font_weight_t m_weight;
#endif
-#ifdef __WXMSW__
- wxCairoContext( wxGraphicsRenderer* renderer, HDC context );
-#endif
};
class wxCairoBitmapData : public wxGraphicsObjectRefData
wxCairoContext( wxGraphicsRenderer* renderer, const wxPrinterDC& dc );
#ifdef __WXGTK__
wxCairoContext( wxGraphicsRenderer* renderer, GdkDrawable *drawable );
+#endif
+#ifdef __WXMSW__
+ wxCairoContext( wxGraphicsRenderer* renderer, HDC context );
#endif
wxCairoContext( wxGraphicsRenderer* renderer, cairo_t *context );
wxCairoContext( wxGraphicsRenderer* renderer, wxWindow *window);
virtual bool ShouldOffset() const
{
+ if ( !m_enableOffset )
+ return false;
+
int penwidth = 0 ;
if ( !m_pen.IsNull() )
{
virtual bool SetAntialiasMode(wxAntialiasMode antialias);
+ virtual bool SetInterpolationQuality(wxInterpolationQuality interpolation);
+
virtual bool SetCompositionMode(wxCompositionMode op);
virtual void BeginLayer(wxDouble opacity);
{
/*
wxBitmap* bmp = pen.GetStipple();
- if ( bmp && bmp->Ok() )
+ if ( bmp && bmp->IsOk() )
{
wxDELETE( m_penImage );
wxDELETE( m_penBrush );
else
{
wxBitmap* bmp = brush.GetStipple();
- if ( bmp && bmp->Ok() )
+ if ( bmp && bmp->IsOk() )
{
wxDELETE( m_brushImage );
m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp->GetHBITMAP(),(HPALETTE)bmp->GetPalette()->GetHPALETTE());
cairo_set_font_face(ctext, m_font);
cairo_set_font_size(ctext, m_size );
#else
- cairo_select_font_face(ctext, m_fontName, m_slant, m_weights );
+ cairo_select_font_face(ctext, m_fontName, m_slant, m_weight );
cairo_set_font_size(ctext, m_size );
#endif
}
{
wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap"));
+#ifdef wxHAS_RAW_BITMAP
int bw = m_width = bmp.GetWidth();
int bh = m_height = bmp.GetHeight();
wxBitmap bmpSource = bmp; // we need a non-const instance
// Create a surface object and copy the bitmap pixel data to it. if the
// image has alpha (or a mask represented as alpha) then we'll use a
// different format and iterator than if it doesn't...
- if (bmpSource.HasAlpha() || bmpSource.GetMask())
+ if (bmpSource.HasAlpha() || (bmpSource.GetMask()
+#ifdef __WXMSW__
+ // this check is needed under wxMSW, but adding this condition to wxGTK
+ // causes an assert when getting alpha pixel data, not sure about Mac.
+ && bmpSource.GetDepth() == 32
+#endif
+ ))
{
m_surface = cairo_image_surface_create_for_data(
m_buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4);
}
}
m_pattern = cairo_pattern_create_for_surface(m_surface);
+#endif // wxHAS_RAW_BITMAP
}
wxCairoBitmapData::~wxCairoBitmapData()
wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxPrinterDC& dc )
: wxGraphicsContext(renderer)
{
+#ifdef __WXMSW__
+ // wxMSW contexts always use MM_ANISOTROPIC, which messes up
+ // text rendering when printing using Cairo. Switch it to MM_TEXT
+ // map mode to avoid this problem.
+ HDC hdc = (HDC)dc.GetHDC();
+ ::SetMapMode(hdc, MM_TEXT);
+ m_mswSurface = cairo_win32_printing_surface_create(hdc);
+ Init( cairo_create(m_mswSurface) );
+#endif
+
#ifdef __WXGTK20__
const wxDCImpl *impl = dc.GetImpl();
Init( (cairo_t*) impl->GetCairoContext() );
+#endif
+ wxSize sz = dc.GetSize();
+ m_width = sz.x;
+ m_height = sz.y;
wxPoint org = dc.GetDeviceOrigin();
cairo_translate( m_context, org.x, org.y );
double sx,sy;
dc.GetUserScale( &sx, &sy );
+
+// TODO: Determine if these fixes are needed on other platforms too.
+// On MSW, without this the printer context will not respect wxDC SetMapMode calls.
+// For example, using dc.SetMapMode(wxMM_POINTS) can let us share printer and screen
+// drawing code
+#ifdef __WXMSW__
+ double lsx,lsy;
+ dc.GetLogicalScale( &lsx, &lsy );
+ sx *= lsx;
+ sy *= lsy;
+#endif
cairo_scale( m_context, sx, sy );
org = dc.GetLogicalOrigin();
cairo_translate( m_context, -org.x, -org.y );
-#endif
}
wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxWindowDC& dc )
: wxGraphicsContext(renderer)
{
+ int width, height;
+ dc.GetSize( &width, &height );
+ m_width = width;
+ m_height = height;
+
+ m_enableOffset = true;
+
+#ifdef __WXMSW__
+ m_mswSurface = cairo_win32_surface_create((HDC)dc.GetHDC());
+ Init( cairo_create(m_mswSurface) );
+#endif
+
#ifdef __WXGTK20__
wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
Init( gdk_cairo_create( impldc->GetGDKWindow() ) );
#endif
#ifdef __WXMAC__
- int width, height;
- dc.GetSize( &width, &height );
CGContextRef cgcontext = (CGContextRef)dc.GetWindow()->MacGetCGContextRef();
cairo_surface_t* surface = cairo_quartz_surface_create_for_cg_context(cgcontext, width, height);
Init( cairo_create( surface ) );
wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& dc )
: wxGraphicsContext(renderer)
{
+ int width, height;
+ dc.GetSize( &width, &height );
+ m_width = width;
+ m_height = height;
+
+ m_enableOffset = true;
+
+#ifdef __WXMSW__
+ m_mswSurface = cairo_win32_surface_create((HDC)dc.GetHDC());
+ Init( cairo_create(m_mswSurface) );
+#endif
+
#ifdef __WXGTK20__
wxGTKDCImpl *impldc = (wxGTKDCImpl*) dc.GetImpl();
Init( gdk_cairo_create( impldc->GetGDKWindow() ) );
#endif
#ifdef __WXMAC__
- int width, height;
- dc.GetSize( &width, &height );
CGContextRef cgcontext = (CGContextRef)dc.GetWindow()->MacGetCGContextRef();
cairo_surface_t* surface = cairo_quartz_surface_create_for_cg_context(cgcontext, width, height);
Init( cairo_create( surface ) );
: wxGraphicsContext(renderer)
{
Init( gdk_cairo_create( drawable ) );
+
+ int width, height;
+ gdk_drawable_get_size( drawable, &width, &height );
+ m_width = width;
+ m_height = height;
}
#endif
: wxGraphicsContext(renderer)
{
m_mswSurface = cairo_win32_surface_create(handle);
- m_context = cairo_create(m_mswSurface);
- PushState();
- PushState();
+ Init( cairo_create(m_mswSurface) );
+ m_width =
+ m_height = 0;
}
#endif
: wxGraphicsContext(renderer)
{
Init( context );
+ m_width =
+ m_height = 0;
}
wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, wxWindow *window)
: wxGraphicsContext(renderer)
{
+ m_enableOffset = true;
#ifdef __WXGTK__
// something along these lines (copied from dcclient)
wxASSERT_MSG( window->m_wxwindow, wxT("wxCairoContext needs a widget") );
Init(gdk_cairo_create(window->GTKGetDrawingWindow()));
+
+ wxSize sz = window->GetSize();
+ m_width = sz.x;
+ m_height = sz.y;
#endif
+
+#ifdef __WXMSW__
+ m_mswSurface = cairo_win32_surface_create((HDC)window->GetHandle());
+ Init(cairo_create(m_mswSurface));
+#endif
+
}
wxCairoContext::~wxCairoContext()
if ( m_context )
{
PopState();
-#ifdef __WXMSW__
- m_mswSurface = cairo_win32_surface_create((HDC)window->GetHandle());
- m_context = cairo_create(m_mswSurface);
-#endif
PopState();
cairo_destroy(m_context);
}
wxDouble scaleX = w / size.GetWidth();
wxDouble scaleY = h / size.GetHeight();
- cairo_scale(m_context, scaleX, scaleY);
// prepare to draw the image
cairo_translate(m_context, x, y);
+ cairo_scale(m_context, scaleX, scaleY);
cairo_set_source(m_context, pattern);
// use the original size here since the context is scaled already...
cairo_rectangle(m_context, 0, 0, size.GetWidth(), size.GetHeight());
return true;
}
+bool wxCairoContext::SetInterpolationQuality(wxInterpolationQuality WXUNUSED(interpolation))
+{
+ // placeholder
+ return false;
+}
+
bool wxCairoContext::SetCompositionMode(wxCompositionMode op)
{
if ( m_composition == op )
virtual wxGraphicsContext * CreateContext( wxWindow* window );
virtual wxGraphicsContext * CreateMeasuringContext();
-
+#ifdef __WXMSW__
+#if wxUSE_ENH_METAFILE
+ virtual wxGraphicsContext * CreateContext( const wxEnhMetaFileDC& dc);
+#endif
+#endif
// Path
virtual wxGraphicsPath CreatePath();
// create a subimage from a native image representation
virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
+protected :
+ bool EnsureIsLoaded();
+ void Load();
+ void Unload();
+ friend class wxCairoModule;
private :
+ int m_loaded;
DECLARE_DYNAMIC_CLASS_NO_COPY(wxCairoRenderer)
} ;
extern wxGraphicsRenderer* gCairoRenderer;
wxGraphicsRenderer* gCairoRenderer = &gs_cairoGraphicsRenderer;
+bool wxCairoRenderer::EnsureIsLoaded()
+{
+#ifndef __WXGTK__
+ Load();
+ return wxCairoInit();
+#else
+ return true;
+#endif
+}
+
+void wxCairoRenderer::Load()
+{
+ wxCairoInit();
+}
+
+void wxCairoRenderer::Unload()
+{
+ wxCairoCleanUp();
+}
+
+// call EnsureIsLoaded() and return returnOnFail value if it fails
+#define ENSURE_LOADED_OR_RETURN(returnOnFail) \
+ if ( !EnsureIsLoaded() ) \
+ return (returnOnFail)
+
wxGraphicsContext * wxCairoRenderer::CreateContext( const wxWindowDC& dc)
{
+ ENSURE_LOADED_OR_RETURN(NULL);
return new wxCairoContext(this,dc);
}
wxGraphicsContext * wxCairoRenderer::CreateContext( const wxMemoryDC& dc)
{
+ ENSURE_LOADED_OR_RETURN(NULL);
return new wxCairoContext(this,dc);
}
wxGraphicsContext * wxCairoRenderer::CreateContext( const wxPrinterDC& dc)
{
+ ENSURE_LOADED_OR_RETURN(NULL);
#ifdef __WXGTK20__
const wxDCImpl *impl = dc.GetImpl();
cairo_t* context = (cairo_t*) impl->GetCairoContext();
return new wxCairoContext(this,dc);
else
#endif
- return NULL;
+ return new wxCairoContext(this,dc);
}
+#ifdef __WXMSW__
+#if wxUSE_ENH_METAFILE
+wxGraphicsContext * wxCairoRenderer::CreateContext( const wxEnhMetaFileDC& WXUNUSED(dc) )
+{
+ ENSURE_LOADED_OR_RETURN(NULL);
+ return NULL;
+}
+#endif
+#endif
+
wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeContext( void * context )
{
+ ENSURE_LOADED_OR_RETURN(NULL);
#ifdef __WXMSW__
return new wxCairoContext(this,(HDC)context);
-#endif
-#ifdef __WXGTK__
+#else
return new wxCairoContext(this,(cairo_t*)context);
#endif
}
wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeWindow( void * window )
{
+ ENSURE_LOADED_OR_RETURN(NULL);
#ifdef __WXGTK__
return new wxCairoContext(this,(GdkDrawable*)window);
#else
+ wxUnusedVar(window);
return NULL;
#endif
}
wxGraphicsContext * wxCairoRenderer::CreateMeasuringContext()
{
+ ENSURE_LOADED_OR_RETURN(NULL);
#ifdef __WXGTK__
return CreateContextFromNativeWindow(gdk_get_default_root_window());
#endif
wxGraphicsContext * wxCairoRenderer::CreateContext( wxWindow* window )
{
+ ENSURE_LOADED_OR_RETURN(NULL);
return new wxCairoContext(this, window );
}
wxGraphicsPath wxCairoRenderer::CreatePath()
{
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsPath);
wxGraphicsPath path;
path.SetRefData( new wxCairoPathData(this) );
return path;
wxDouble tx, wxDouble ty)
{
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsMatrix);
wxGraphicsMatrix m;
wxCairoMatrixData* data = new wxCairoMatrixData( this );
data->Set( a,b,c,d,tx,ty ) ;
wxGraphicsPen wxCairoRenderer::CreatePen(const wxPen& pen)
{
- if ( !pen.Ok() || pen.GetStyle() == wxPENSTYLE_TRANSPARENT )
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsPen);
+ if ( !pen.IsOk() || pen.GetStyle() == wxPENSTYLE_TRANSPARENT )
return wxNullGraphicsPen;
else
{
wxGraphicsBrush wxCairoRenderer::CreateBrush(const wxBrush& brush )
{
- if ( !brush.Ok() || brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT )
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
+ if ( !brush.IsOk() || brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT )
return wxNullGraphicsBrush;
else
{
wxDouble x2, wxDouble y2,
const wxGraphicsGradientStops& stops)
{
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
wxGraphicsBrush p;
wxCairoBrushData* d = new wxCairoBrushData( this );
d->CreateLinearGradientBrush(x1, y1, x2, y2, stops);
wxDouble xc, wxDouble yc, wxDouble r,
const wxGraphicsGradientStops& stops)
{
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBrush);
wxGraphicsBrush p;
wxCairoBrushData* d = new wxCairoBrushData( this );
d->CreateRadialGradientBrush(xo, yo, xc, yc, r, stops);
// sets the font
wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour &col )
{
- if ( font.Ok() )
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsFont);
+ if ( font.IsOk() )
{
wxGraphicsFont p;
p.SetRefData(new wxCairoFontData( this , font, col ));
wxGraphicsBitmap wxCairoRenderer::CreateBitmap( const wxBitmap& bmp )
{
- if ( bmp.Ok() )
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
+ if ( bmp.IsOk() )
{
wxGraphicsBitmap p;
p.SetRefData(new wxCairoBitmapData( this , bmp ));
wxGraphicsBitmap wxCairoRenderer::CreateBitmapFromNativeBitmap( void* bitmap )
{
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
if ( bitmap != NULL )
{
wxGraphicsBitmap p;
wxDouble WXUNUSED(w),
wxDouble WXUNUSED(h))
{
+ ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap);
wxFAIL_MSG("wxCairoRenderer::CreateSubBitmap is not implemented.");
return wxNullGraphicsBitmap;
}