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:
parent
977a41ec3e
commit
bf02a7f976
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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() )
|
||||
|
@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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") );
|
||||
|
||||
|
@ -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 ®ion )
|
||||
@ -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 )
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user