switching to compositing operators (fixes #9881), adding layers

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58917 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Csomor 2009-02-15 16:52:05 +00:00
parent 977a41ec3e
commit bf02a7f976
6 changed files with 538 additions and 154 deletions

View File

@ -20,6 +20,38 @@
#include "wx/dynarray.h"
#include "wx/dc.h"
enum wxAntialiasMode
{
wxANTIALIAS_NONE, // should be 0
wxANTIALIAS_DEFAULT,
};
enum wxCompositionMode
{
// R = Result, S = Source, D = Destination, premultiplied with alpha
// Ra, Sa, Da their alpha components
// classic Porter-Duff compositions
// http://keithp.com/~keithp/porterduff/p253-porter.pdf
wxCOMPOSITION_CLEAR, /* R = 0 */
wxCOMPOSITION_SOURCE, /* R = S */
wxCOMPOSITION_OVER, /* R = S + D*(1 - Sa) */
wxCOMPOSITION_IN, /* R = S*Da */
wxCOMPOSITION_OUT, /* R = S*(1 - Da) */
wxCOMPOSITION_ATOP, /* R = S*Da + D*(1 - Sa) */
wxCOMPOSITION_DEST, /* R = D, essentially a noop */
wxCOMPOSITION_DEST_OVER, /* R = S*(1 - Da) + D */
wxCOMPOSITION_DEST_IN, /* R = D*Sa */
wxCOMPOSITION_DEST_OUT, /* R = D*(1 - Sa) */
wxCOMPOSITION_DEST_ATOP, /* R = S*(1 - Da) + D*Sa */
wxCOMPOSITION_XOR, /* R = S*(1 - Da) + D*(1 - Sa) */
// mathematical compositions
wxCOMPOSITION_ADD, /* R = S + D */
};
class WXDLLIMPEXP_FWD_CORE wxWindowDC;
class WXDLLIMPEXP_FWD_CORE wxMemoryDC;
#if wxUSE_PRINTING_ARCHITECTURE
@ -356,11 +388,17 @@ public:
// returns the native context
virtual void * GetNativeContext() = 0;
// returns the current logical function
virtual wxRasterOperationMode GetLogicalFunction() const { return m_logicalFunction; }
// returns the current shape antialiasing mode
virtual wxAntialiasMode GetAntialiasMode() const { return m_antialias; }
// sets the antialiasing mode, returns true if it supported
virtual bool SetAntialiasMode(wxAntialiasMode antialias) = 0;
// sets the current logical function, returns true if it supported
virtual bool SetLogicalFunction(wxRasterOperationMode function);
// returns the current compositing operator
virtual wxCompositionMode GetCompositionMode() const { return m_composition; }
// sets the compositing operator, returns true if it supported
virtual bool SetCompositionMode(wxCompositionMode op) = 0;
// returns the size of the graphics context in device coordinates
virtual void GetSize( wxDouble* width, wxDouble* height);
@ -375,6 +413,14 @@ public:
// returns the alpha on this context
virtual wxDouble GetAlpha() const;
#endif
// all rendering is done into a fully transparent temporary context
virtual void BeginLayer(wxDouble opacity) = 0;
// composites back the drawings into the content with the opacity given at
// the BeginLayer call
virtual void EndLayer() = 0;
//
// transformation : changes the current transformation matrix CTM of the context
//
@ -477,7 +523,7 @@ public:
// draws a polygon
virtual void DrawLines( size_t n, const wxPoint2DDouble *points, wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
// draws a polygon
// draws a rectangle
virtual void DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h);
// draws an ellipse
@ -496,7 +542,8 @@ protected:
wxGraphicsPen m_pen;
wxGraphicsBrush m_brush;
wxGraphicsFont m_font;
wxRasterOperationMode m_logicalFunction;
wxAntialiasMode m_antialias;
wxCompositionMode m_composition;
protected:
// implementations of overloaded public functions: we use different names

View File

@ -53,6 +53,43 @@ static inline double DegToRad(double deg)
return (deg * M_PI) / 180.0;
}
static bool TranslateRasterOp(wxRasterOperationMode function, wxCompositionMode *op)
{
switch ( function )
{
case wxCOPY: // (default) src
*op = wxCOMPOSITION_SOURCE; //
break;
case wxOR: // src OR dst
*op = wxCOMPOSITION_ADD;
break;
case wxNO_OP: // dst
*op = wxCOMPOSITION_DEST; // ignore the source
break;
case wxCLEAR: // 0
*op = wxCOMPOSITION_CLEAR;// clear dst
break;
case wxXOR: // src XOR dst
*op = wxCOMPOSITION_XOR;
break;
case wxAND: // src AND dst
case wxAND_INVERT: // (NOT src) AND dst
case wxAND_REVERSE:// src AND (NOT dst)
case wxEQUIV: // (NOT src) XOR dst
case wxINVERT: // NOT dst
case wxNAND: // (NOT src) OR (NOT dst)
case wxNOR: // (NOT src) AND (NOT dst)
case wxOR_INVERT: // (NOT src) OR dst
case wxOR_REVERSE: // src OR (NOT dst)
case wxSET: // 1
case wxSRC_INVERT: // NOT src
default:
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// wxDC bridge class
//-----------------------------------------------------------------------------
@ -456,10 +493,16 @@ void wxGCDCImpl::SetLogicalFunction( wxRasterOperationMode function )
return;
m_logicalFunction = function;
if ( m_graphicContext->SetLogicalFunction( function ) )
m_logicalFunctionSupported=true;
wxCompositionMode mode;
m_logicalFunctionSupported = TranslateRasterOp( function, &mode);
if (m_logicalFunctionSupported)
m_logicalFunctionSupported = m_graphicContext->SetCompositionMode(mode);
if (mode == wxCOMPOSITION_XOR)
m_graphicContext->SetAntialiasMode(wxANTIALIAS_NONE);
else
m_logicalFunctionSupported=false;
m_graphicContext->SetAntialiasMode(wxANTIALIAS_DEFAULT);
}
bool wxGCDCImpl::DoFloodFill(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
@ -822,53 +865,71 @@ bool wxGCDCImpl::DoStretchBlit(
if ( logical_func == wxNO_OP )
return true;
else if ( !m_graphicContext->SetLogicalFunction( logical_func ) )
wxCompositionMode mode;
if ( !TranslateRasterOp(logical_func, &mode) )
{
wxFAIL_MSG( wxT("Blitting is only supported with wxCOPY logical operation.") );
wxFAIL_MSG( wxT("Blitting is not supported with this logical operation.") );
return false;
}
if (xsrcMask == -1 && ysrcMask == -1)
bool retval = true;
wxCompositionMode formerMode = m_graphicContext->GetCompositionMode();
if (m_graphicContext->SetCompositionMode(mode))
{
xsrcMask = xsrc;
ysrcMask = ysrc;
wxAntialiasMode formerAa = m_graphicContext->GetAntialiasMode();
if (mode == wxCOMPOSITION_XOR)
{
m_graphicContext->SetAntialiasMode(wxANTIALIAS_NONE);
}
if (xsrcMask == -1 && ysrcMask == -1)
{
xsrcMask = xsrc;
ysrcMask = ysrc;
}
wxRect subrect(source->LogicalToDeviceX(xsrc),
source->LogicalToDeviceY(ysrc),
source->LogicalToDeviceXRel(srcWidth),
source->LogicalToDeviceYRel(srcHeight));
// if needed clip the subrect down to the size of the source DC
wxCoord sw, sh;
source->GetSize(&sw, &sh);
sw = source->LogicalToDeviceXRel(sw);
sh = source->LogicalToDeviceYRel(sh);
if (subrect.x + subrect.width > sw)
subrect.width = sw - subrect.x;
if (subrect.y + subrect.height > sh)
subrect.height = sh - subrect.y;
wxBitmap blit = source->GetAsBitmap( &subrect );
if ( blit.IsOk() )
{
if ( !useMask && blit.GetMask() )
blit.SetMask(NULL);
m_graphicContext->DrawBitmap( blit, xdest, ydest,
dstWidth, dstHeight);
}
else
{
wxFAIL_MSG( wxT("Cannot Blit. Unable to get contents of DC as bitmap.") );
retval = false;
}
if (mode == wxCOMPOSITION_XOR)
{
m_graphicContext->SetAntialiasMode(formerAa);
}
}
// reset composition
m_graphicContext->SetCompositionMode(formerMode);
wxRect subrect(source->LogicalToDeviceX(xsrc),
source->LogicalToDeviceY(ysrc),
source->LogicalToDeviceXRel(srcWidth),
source->LogicalToDeviceYRel(srcHeight));
// if needed clip the subrect down to the size of the source DC
wxCoord sw, sh;
source->GetSize(&sw, &sh);
sw = source->LogicalToDeviceXRel(sw);
sh = source->LogicalToDeviceYRel(sh);
if (subrect.x + subrect.width > sw)
subrect.width = sw - subrect.x;
if (subrect.y + subrect.height > sh)
subrect.height = sh - subrect.y;
wxBitmap blit = source->GetAsBitmap( &subrect );
if ( blit.IsOk() )
{
if ( !useMask && blit.GetMask() )
blit.SetMask(NULL);
m_graphicContext->DrawBitmap( blit, xdest, ydest,
dstWidth, dstHeight);
}
else
{
wxFAIL_MSG( wxT("Cannot Blit. Unable to get contents of DC as bitmap.") );
return false;
}
// reset logical function
m_graphicContext->SetLogicalFunction( m_logicalFunction );
return true;
return retval;
}
void wxGCDCImpl::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,

View File

@ -501,9 +501,11 @@ void wxGraphicsPathData::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2,
IMPLEMENT_ABSTRACT_CLASS(wxGraphicsContext, wxObject)
wxGraphicsContext::wxGraphicsContext(wxGraphicsRenderer* renderer) : wxGraphicsObject(renderer)
wxGraphicsContext::wxGraphicsContext(wxGraphicsRenderer* renderer) :
wxGraphicsObject(renderer),
m_antialias(wxANTIALIAS_DEFAULT),
m_composition(wxCOMPOSITION_OVER)
{
m_logicalFunction = wxCOPY;
}
wxGraphicsContext::~wxGraphicsContext()
@ -589,16 +591,6 @@ void wxGraphicsContext::SetFont( const wxGraphicsFont& font )
m_font = font;
}
bool wxGraphicsContext::SetLogicalFunction( wxRasterOperationMode function )
{
if ( function == wxCOPY )
{
m_logicalFunction = function;
return true;
}
return false;
}
void wxGraphicsContext::SetFont( const wxFont& font, const wxColour& colour )
{
if ( font.Ok() )

View File

@ -347,8 +347,14 @@ public:
virtual void * GetNativeContext();
virtual bool SetLogicalFunction( wxRasterOperationMode function );
virtual bool SetAntialiasMode(wxAntialiasMode antialias);
virtual bool SetCompositionMode(wxCompositionMode op);
virtual void BeginLayer(wxDouble opacity);
virtual void EndLayer();
virtual void StrokePath( const wxGraphicsPath& p );
virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxWINDING_RULE );
@ -380,6 +386,8 @@ private:
virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y );
cairo_t* m_context;
wxVector<float> m_layerOpacities;
wxDECLARE_NO_COPY_CLASS(wxCairoContext);
};
@ -1536,54 +1544,98 @@ void * wxCairoContext::GetNativeContext()
return m_context;
}
// Cairo doesn't support bitwise logical function (a.k.a. ROP, raster output
// mode). Cairo supports Porter-Duff compositing operators, but they are quite
// different, although in some cases have similar names.
bool wxCairoContext::SetLogicalFunction( wxRasterOperationMode function )
bool wxCairoContext::SetAntialiasMode(wxAntialiasMode antialias)
{
if (m_logicalFunction == function)
if (m_antialias == antialias)
return true;
cairo_operator_t op;
switch ( function )
m_antialias = antialias;
cairo_antialias_t antialiasMode;
switch (antialias)
{
case wxCOPY: // (default) src
op = CAIRO_OPERATOR_OVER; // (also default)
case wxANTIALIAS_DEFAULT:
antialiasMode = CAIRO_ANTIALIAS_DEFAULT;
break;
case wxOR: // src OR dst
op = CAIRO_OPERATOR_ADD;
case wxANTIALIAS_NONE:
antialiasMode = CAIRO_ANTIALIAS_NONE;
break;
case wxNO_OP: // dst
op = CAIRO_OPERATOR_DEST; // ignore the source
break;
case wxCLEAR: // 0
op = CAIRO_OPERATOR_CLEAR;// clear dst
break;
case wxAND: // src AND dst
case wxAND_INVERT: // (NOT src) AND dst
case wxAND_REVERSE:// src AND (NOT dst)
case wxEQUIV: // (NOT src) XOR dst
case wxINVERT: // NOT dst
case wxNAND: // (NOT src) OR (NOT dst)
case wxNOR: // (NOT src) AND (NOT dst)
case wxOR_INVERT: // (NOT src) OR dst
case wxOR_REVERSE: // src OR (NOT dst)
case wxSET: // 1
case wxSRC_INVERT: // NOT src
//wxXOR does _not_ correspond to CAIRO_OPERATOR_XOR
case wxXOR: // src XOR dst
default:
return false;
}
m_logicalFunction = function;
cairo_set_operator(m_context, op);
cairo_set_antialias(m_context, antialiasMode);
return true;
}
bool wxCairoContext::SetCompositionMode(wxCompositionMode op)
{
if ( m_composition == op )
return true;
m_composition = op;
cairo_operator_t cop;
switch (op)
{
case wxCOMPOSITION__CLEAR:
cop = CAIRO_OPERATOR_CLEAR;
break;
case wxCOMPOSITION_SOURCE:
cop = CAIRO_OPERATOR_SOURCE;
break;
case wxCOMPOSITION_OVER:
cop = CAIRO_OPERATOR_OVER;
break;
case wxCOMPOSITION_IN:
cop = CAIRO_OPERATOR_IN;
break;
case wxCOMPOSITION_OUT:
cop = CAIRO_OPERATOR_OUT;
break;
case wxCOMPOSITION_ATOP:
cop = CAIRO_OPERATOR_ATOP;
break;
case wxCOMPOSITION_DEST:
cop = CAIRO_OPERATOR_DEST;
break;
case wxCOMPOSITION_DEST_OVER:
cop = CAIRO_OPERATOR_DEST_OVER;
break;
case wxCOMPOSITION_DEST_IN:
cop = CAIRO_OPERATOR_DEST_IN;
break;
case wxCOMPOSITION_DEST_OUT:
cop = CAIRO_OPERATOR_DEST_OUT;
break;
case wxCOMPOSITION_DEST_ATOP:
cop = CAIRO_OPERATOR_DEST_ATOP;
break;
case wxCOMPOSITION_XOR:
cop = CAIRO_OPERATOR_XOR;
break;
case wxCOMPOSITION_ADD:
cop = CAIRO_OPERATOR_ADD;
break;
default:
return false;
}
cairo_set_operator(m_context, cop);
return true;
}
void wxCairoContext::BeginLayer(wxDouble opacity)
{
m_layerOpacities.push_back(opacity);
cairo_push_group(m_context);
}
void wxCairoContext::EndLayer()
{
float opacity = m_layerOpacities.back();
m_layerOpacities.pop_back();
cairo_pop_group_to_source(m_context);
cairo_paint_with_alpha(m_context,opacity);
}
//-----------------------------------------------------------------------------
// wxCairoRenderer declaration
//-----------------------------------------------------------------------------

View File

@ -304,6 +304,14 @@ public:
// draws a polygon
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 );
@ -1110,6 +1118,9 @@ void wxGDIPlusContext::ResetClip()
void wxGDIPlusContext::StrokeLines( size_t n, const wxPoint2DDouble *points)
{
if (m_composition == wxCOMPOSITION_DEST)
return;
if ( !m_pen.IsNull() )
{
wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
@ -1127,6 +1138,9 @@ void wxGDIPlusContext::StrokeLines( size_t n, const wxPoint2DDouble *points)
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++)
@ -1144,6 +1158,9 @@ void wxGDIPlusContext::DrawLines( size_t n, const wxPoint2DDouble *points, wxPol
void wxGDIPlusContext::StrokePath( const wxGraphicsPath& path )
{
if (m_composition == wxCOMPOSITION_DEST)
return;
if ( !m_pen.IsNull() )
{
wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
@ -1153,6 +1170,9 @@ void wxGDIPlusContext::StrokePath( const wxGraphicsPath& path )
void wxGDIPlusContext::FillPath( const wxGraphicsPath& path , wxPolygonFillMode fillStyle )
{
if (m_composition == wxCOMPOSITION_DEST)
return;
if ( !m_brush.IsNull() )
{
wxGDIPlusOffsetHelper helper( m_context , ShouldOffset() );
@ -1162,6 +1182,66 @@ void wxGDIPlusContext::FillPath( const wxGraphicsPath& path , wxPolygonFillMode
}
}
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) );
@ -1192,6 +1272,9 @@ void wxGDIPlusContext::PopState()
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 )
{
@ -1215,6 +1298,9 @@ void wxGDIPlusContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y,
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();
@ -1278,6 +1364,9 @@ void wxGDIPlusContext::DoDrawFilledText(const wxString& str,
wxDouble x, wxDouble y,
const wxGraphicsBrush& brush)
{
if (m_composition == wxCOMPOSITION_DEST)
return;
wxCHECK_RET( !m_font.IsNull(),
wxT("wxGDIPlusContext::DrawText - no valid font set") );

View File

@ -5,7 +5,7 @@
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Stefan Csomor
// copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
@ -77,6 +77,35 @@ extern bool wxOSXLockFocus( WXWidget view) ;
extern void wxOSXUnlockFocus( WXWidget view) ;
#endif
#if 1 // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
// TODO test whether this private API also works under 10.3
// copying values from NSCompositingModes (see also webkit and cairo sources)
typedef enum CGCompositeOperation {
kCGCompositeOperationClear = 0,
kCGCompositeOperationCopy = 1,
kCGCompositeOperationSourceOver = 2,
kCGCompositeOperationSourceIn = 3,
kCGCompositeOperationSourceOut = 4,
kCGCompositeOperationSourceAtop = 5,
kCGCompositeOperationDestinationOver = 6,
kCGCompositeOperationDestinationIn = 7,
kCGCompositeOperationDestinationOut = 8,
kCGCompositeOperationDestinationAtop = 9,
kCGCompositeOperationXOR = 10,
kCGCompositeOperationPlusDarker = 11,
// NS only, unsupported by CG : Highlight
kCGCompositeOperationPlusLighter = 12
} CGCompositeOperation ;
extern "C"
{
CG_EXTERN void CGContextSetCompositeOperation (CGContextRef context, int operation);
} ;
#endif
//-----------------------------------------------------------------------------
// constants
@ -534,12 +563,7 @@ void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
}
else
{
if ( context->GetLogicalFunction() == wxINVERT || context->GetLogicalFunction() == wxXOR )
{
CGContextSetRGBStrokeColor( cg , (CGFloat) 1.0,(CGFloat) 1.0 , (CGFloat) 1.0, (CGFloat) 1.0 );
}
else
CGContextSetStrokeColorWithColor( cg , m_color );
CGContextSetStrokeColorWithColor( cg , m_color );
}
}
@ -829,7 +853,7 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere
OSStatus status = noErr;
m_macATSUIStyle = NULL;
status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
status = ATSUCreateAndcopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
@ -1316,7 +1340,14 @@ public:
virtual void * GetNativeContext();
bool SetLogicalFunction( wxRasterOperationMode function );
virtual bool SetAntialiasMode(wxAntialiasMode antialias);
virtual bool SetCompositionMode(wxCompositionMode op);
virtual void BeginLayer(wxDouble opacity);
virtual void EndLayer();
//
// transformation
//
@ -1627,69 +1658,160 @@ bool wxMacCoreGraphicsContext::EnsureIsValid()
return m_cgContext != NULL;
}
// TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes)
bool wxMacCoreGraphicsContext::SetLogicalFunction( wxRasterOperationMode function )
bool wxMacCoreGraphicsContext::SetAntialiasMode(wxAntialiasMode antialias)
{
if (m_logicalFunction == function)
return true;
if (EnsureIsValid()==false)
return true;
bool retval = false;
bool shouldAntiAlias = true;
CGBlendMode mode = kCGBlendModeNormal;
#if defined(__WXMAC__) && ( wxOSX_USE_IPHONE || ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 ) )
#if wxOSX_USE_IPHONE
if ( 1 )
#else
if ( UMAGetSystemVersion() >= 0x1050 )
#endif
if (m_antialias == antialias)
return true;
m_antialias = antialias;
bool antialiasMode;
switch (antialias)
{
retval = true;
switch ( function )
case wxANTIALIAS_DEFAULT:
antialiasMode = true;
break;
case wxANTIALIAS_NONE:
antialiasMode = false;
break;
default:
return false;
}
CGContextSetShouldAntialias(m_cgContext, antialiasMode);
return true;
}
bool wxMacCoreGraphicsContext::SetCompositionMode(wxCompositionMode op)
{
if (EnsureIsValid()==false)
return true;
if ( m_composition == op )
return true;
m_composition = op;
if (m_composition == wxCOMPOSITION_DEST)
return true;
#if wxOSX_USE_COCOA_OR_CARBON
#if 1 // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
if ( UMAGetSystemVersion() < 0x1060 )
{
CGCompositeOperation cop = kCGCompositeOperationSourceOver;
CGBlendMode mode = kCGBlendModeNormal;
switch( op )
{
// TODO find best corresponding porter duff modes
case wxCOPY :
mode = kCGBlendModeCopy;
break;
case wxCLEAR :
mode = kCGBlendModeClear;
break;
case wxXOR :
mode = kCGBlendModeXOR;
shouldAntiAlias = false;
break;
default :
retval = false;
break;
case wxCOMPOSITION_CLEAR:
cop = kCGCompositeOperationClear;
break;
case wxCOMPOSITION_SOURCE:
cop = kCGCompositeOperationCopy;
break;
case wxCOMPOSITION_OVER:
mode = kCGBlendModeNormal;
break;
case wxCOMPOSITION_IN:
cop = kCGCompositeOperationSourceIn;
break;
case wxCOMPOSITION_OUT:
cop = kCGCompositeOperationSourceOut;
break;
case wxCOMPOSITION_ATOP:
cop = kCGCompositeOperationSourceAtop;
break;
case wxCOMPOSITION_DEST_OVER:
cop = kCGCompositeOperationDestinationOver;
break;
case wxCOMPOSITION_DEST_IN:
cop = kCGCompositeOperationDestinationIn;
break;
case wxCOMPOSITION_DEST_OUT:
cop = kCGCompositeOperationDestinationOut;
break;
case wxCOMPOSITION_DEST_ATOP:
cop = kCGCompositeOperationDestinationAtop;
break;
case wxCOMPOSITION_XOR:
cop = kCGCompositeOperationXOR;
break;
case wxCOMPOSITION_ADD:
mode = kCGBlendModePlusLighter ;
break;
default:
return false;
}
if ( cop != kCGCompositeOperationSourceOver )
CGContextSetCompositeOperation(m_cgContext, cop);
else
CGContextSetBlendMode(m_cgContext, mode);
}
else
#endif
#endif
{
if ( function == wxCOPY )
CGBlendMode mode = kCGBlendModeNormal;
switch( op )
{
retval = true;
}
else if ( function == wxINVERT || function == wxXOR )
{
// change color to white
mode = kCGBlendModeExclusion;
shouldAntiAlias = false;
retval = true;
case wxCOMPOSITION_CLEAR:
mode = kCGBlendModeClear;
break;
case wxCOMPOSITION_SOURCE:
mode = kCGBlendModeCopy;
break;
case wxCOMPOSITION_OVER:
mode = kCGBlendModeNormal;
break;
case wxCOMPOSITION_IN:
mode = kCGBlendModeSourceIn;
break;
case wxCOMPOSITION_OUT:
mode = kCGBlendModeSourceOut;
break;
case wxCOMPOSITION_ATOP:
mode = kCGBlendModeSourceAtop;
break;
case wxCOMPOSITION_DEST_OVER:
mode = kCGBlendModeDestinationOver;
break;
case wxCOMPOSITION_DEST_IN:
mode = kCGBlendModeDestinationIn;
break;
case wxCOMPOSITION_DEST_OUT:
mode = kCGBlendModeDestinationOut;
break;
case wxCOMPOSITION_DEST_ATOP:
mode = kCGBlendModeDestinationAtop;
break;
case wxCOMPOSITION_XOR:
mode = kCGBlendModeXOR;
break;
case wxCOMPOSITION_ADD:
mode = kCGBlendModePlusLighter ;
break;
default:
return false;
}
CGContextSetBlendMode(m_cgContext, mode);
}
return true;
}
if (retval)
{
m_logicalFunction = function;
CGContextSetBlendMode( m_cgContext, mode );
CGContextSetShouldAntialias(m_cgContext, shouldAntiAlias);
}
return retval ;
void wxMacCoreGraphicsContext::BeginLayer(wxDouble opacity)
{
CGContextSaveGState(m_cgContext);
CGContextSetAlpha(m_cgContext, opacity);
CGContextBeginTransparencyLayer(m_cgContext, 0);
}
void wxMacCoreGraphicsContext::EndLayer()
{
CGContextEndTransparencyLayer(m_cgContext);
CGContextRestoreGState(m_cgContext);
}
void wxMacCoreGraphicsContext::Clip( const wxRegion &region )
@ -1782,6 +1904,9 @@ void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path )
if (EnsureIsValid()==false)
return;
if (m_composition == wxCOMPOSITION_DEST)
return;
wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() );
((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this);
@ -1794,6 +1919,9 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , wxPolygonF
if (EnsureIsValid()==false)
return;
if (m_composition == wxCOMPOSITION_DEST)
return;
if ( !m_brush.IsNull() && ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
{
// when using shading, we cannot draw pen and brush at the same time
@ -1847,6 +1975,9 @@ void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , wxPolygonF
if (EnsureIsValid()==false)
return;
if (m_composition == wxCOMPOSITION_DEST)
return;
if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
{
CGContextSaveGState( m_cgContext );
@ -1944,6 +2075,9 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble
{
if (EnsureIsValid()==false)
return;
if (m_composition == wxCOMPOSITION_DEST)
return;
#ifdef __WXMAC__
wxMacCoreGraphicsBitmapData* refdata =static_cast<wxMacCoreGraphicsBitmapData*>(bmp.GetRefData());
@ -1984,6 +2118,9 @@ void wxMacCoreGraphicsContext::DrawIcon( const wxIcon &icon, wxDouble x, wxDoubl
if (EnsureIsValid()==false)
return;
if (m_composition == wxCOMPOSITION_DEST)
return;
CGRect r = CGRectMake( (CGFloat) 0.0 , (CGFloat) 0.0 , (CGFloat) w , (CGFloat) h );
CGContextSaveGState( m_cgContext );
CGContextTranslateCTM( m_cgContext,(CGFloat) x ,(CGFloat) (y + h) );
@ -2018,6 +2155,9 @@ void wxMacCoreGraphicsContext::DoDrawText( const wxString &str, wxDouble x, wxDo
if (EnsureIsValid()==false)
return;
if (m_composition == wxCOMPOSITION_DEST)
return;
#if wxOSX_USE_CORE_TEXT
if ( UMAGetSystemVersion() >= 0x1050 )
{
@ -2078,6 +2218,9 @@ void wxMacCoreGraphicsContext::DoDrawRotatedText(const wxString &str,
if (EnsureIsValid()==false)
return;
if (m_composition == wxCOMPOSITION_DEST)
return;
#if wxOSX_USE_CORE_TEXT
if ( UMAGetSystemVersion() >= 0x1050 )
{