#ifndef WX_PRECOMP
#include "wx/dcclient.h"
+ #include "wx/dcmemory.h"
#include "wx/log.h"
#include "wx/region.h"
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
typedef float CGFloat;
#endif
+#ifndef wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 1
+#else
+ #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
+#endif
+#endif
//-----------------------------------------------------------------------------
// constants
void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
- if ( UMAGetSystemVersion() >= 0x1040 )
+ if ( CGContextStrokeLineSegments!=NULL )
{
CGContextStrokeLineSegments( ctxRef , pts , count );
}
if ( bmp && bmp->Ok() )
{
m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) );
- m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeTranslation( 0,0 ) ) ) );
+ m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
m_patternColorComponents = new CGFloat[1] ;
m_patternColorComponents[0] = 1.0;
m_isPattern = true;
{
m_isPattern = true;
m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
- m_pattern.Set( *( new HatchPattern( pen.GetStyle() , CGAffineTransformMakeTranslation( 0,0 ) ) ) );
+ m_pattern.Set( *( new HatchPattern( pen.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
m_patternColorComponents = new CGFloat[4] ;
m_patternColorComponents[0] = pen.GetColour().Red() / 255.0;
m_patternColorComponents[1] = pen.GetColour().Green() / 255.0;
if ( m_isPattern )
{
+ CGAffineTransform matrix = CGContextGetCTM( cg );
+ CGContextSetPatternPhase( cg, CGSizeMake(matrix.tx, matrix.ty) );
CGContextSetStrokeColorSpace( cg , m_colorSpace );
CGContextSetStrokePattern( cg, m_pattern , m_patternColorComponents );
}
else
{
- CGContextSetStrokeColorWithColor( cg , m_color );
+ if ( context->GetLogicalFunction() == wxINVERT || context->GetLogicalFunction() == wxXOR )
+ {
+ CGContextSetRGBStrokeColor( cg , 1.0, 1.0 , 1.0, 1.0 );
+ }
+ else
+ CGContextSetStrokeColorWithColor( cg , m_color );
}
}
if ( brush.GetStyle() == wxSOLID )
{
- float components[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
+ if ( brush.MacGetBrushKind() == kwxMacBrushTheme )
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if ( HIThemeBrushCreateCGColor != 0 )
+ {
+ CGColorRef color ;
+ HIThemeBrushCreateCGColor( brush.MacGetTheme(), &color );
+ m_color.Set( color ) ;
+ }
+ else
+#endif
+ {
+ // as close as we can get, unfortunately < 10.4 things get difficult
+ RGBColor color;
+ GetThemeBrushAsColor( brush.MacGetTheme(), 32, true, &color );
+ float components[4] = { (CGFloat) color.red / 65536,
+ (CGFloat) color.green / 65536, (CGFloat) color.blue / 65536, 1 } ;
+ m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+ }
+ }
+ else
+ {
+ float components[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 ,
brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 } ;
- m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+ m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ;
+ }
}
else if ( brush.IsHatch() )
{
m_isPattern = true;
m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
- m_pattern.Set( *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeTranslation( 0,0 ) ) ) );
+ m_pattern.Set( *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
m_patternColorComponents = new CGFloat[4] ;
m_patternColorComponents[0] = brush.GetColour().Red() / 255.0;
m_patternColorComponents = new CGFloat[1] ;
m_patternColorComponents[0] = 1.0;
m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) );
- m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeTranslation( 0,0 ) ) ) );
+ m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
}
}
}
if ( m_isShading )
{
+ // nothing to set as shades are processed by clipping using the path and filling
}
else
{
if ( m_isPattern )
{
+ CGAffineTransform matrix = CGContextGetCTM( cg );
+ CGContextSetPatternPhase( cg, CGSizeMake(matrix.tx, matrix.ty) );
CGContextSetFillColorSpace( cg , m_colorSpace );
CGContextSetFillPattern( cg, m_pattern , m_patternColorComponents );
}
virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
wxDouble tx=0.0, wxDouble ty=0.0);
+ // gets the component valuess of the matrix
+ virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL,
+ wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
+
// makes this the inverse matrix
virtual void Invert();
m_matrix = CGAffineTransformMake(a,b,c,d,tx,ty);
}
+// gets the component valuess of the matrix
+void wxMacCoreGraphicsMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
+ wxDouble* d, wxDouble* tx, wxDouble* ty) const
+{
+ if (a) *a = m_matrix.a;
+ if (b) *b = m_matrix.b;
+ if (c) *c = m_matrix.c;
+ if (d) *d = m_matrix.d;
+ if (tx) *tx= m_matrix.tx;
+ if (ty) *ty= m_matrix.ty;
+}
+
// makes this the inverse matrix
void wxMacCoreGraphicsMatrixData::Invert()
{
bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
{
const CGAffineTransform* tm = (CGAffineTransform*) t->GetNativeMatrix();
- return (
- m_matrix.a == tm->a &&
- m_matrix.b == tm->b &&
- m_matrix.c == tm->c &&
- m_matrix.d == tm->d &&
- m_matrix.tx == tm->tx &&
- m_matrix.ty == tm->ty ) ;
-
- return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if ( CGAffineTransformEqualToTransform!=NULL )
+ {
+ return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
+ }
+ else
+#endif
+ {
+ return (
+ m_matrix.a == tm->a &&
+ m_matrix.b == tm->b &&
+ m_matrix.c == tm->c &&
+ m_matrix.d == tm->d &&
+ m_matrix.tx == tm->tx &&
+ m_matrix.ty == tm->ty ) ;
+ }
}
// return true if this is the identity matrix
bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, int fillStyle) const
{
- return CGPathContainsPoint( m_path, NULL, CGPointMake(x,y), fillStyle == wxODDEVEN_RULE );
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ if ( CGPathContainsPoint!=NULL )
+ {
+ return CGPathContainsPoint( m_path, NULL, CGPointMake(x,y), fillStyle == wxODDEVEN_RULE );
+ }
+ else
+#endif
+ {
+ // TODO : implementation for 10.3
+ CGRect bounds = CGPathGetBoundingBox( m_path ) ;
+ return CGRectContainsPoint( bounds, CGPointMake(x,y) ) == 1;
+ }
}
//
virtual void * GetNativeContext();
+ bool SetLogicalFunction( int function );
//
// transformation
//
virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE );
virtual bool ShouldOffset() const
- {
+ {
int penwidth = 0 ;
if ( !m_pen.IsNull() )
{
m_releaseContext = true;
if ( !HIShapeIsEmpty(m_clipRgn) )
{
- HIShapeReplacePathInCGContext( m_clipRgn, m_cgContext );
+ // the clip region is in device coordinates, so we convert this again to user coordinates
+ wxMacCFRefHolder<HIMutableShapeRef> hishape ;
+ hishape.Set( HIShapeCreateMutableCopy( m_clipRgn ) );
+ CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform);
+ HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y );
+ HIShapeReplacePathInCGContext( hishape, m_cgContext );
CGContextClip( m_cgContext );
}
CGContextSaveGState( m_cgContext );
}
}
+bool wxMacCoreGraphicsContext::SetLogicalFunction( int function )
+{
+ if (m_logicalFunction == function)
+ return true;
+
+ EnsureIsValid();
+
+ bool retval = false;
+
+ if ( function == wxCOPY )
+ {
+ retval = true;
+#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
+ if ( CGContextSetBlendMode != NULL )
+ {
+ CGContextSetBlendMode( m_cgContext, kCGBlendModeNormal );
+ CGContextSetShouldAntialias( m_cgContext, true );
+ }
+#endif
+ }
+ else if ( function == wxINVERT || function == wxXOR )
+ {
+#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
+ if ( CGContextSetBlendMode != NULL )
+ {
+ // change color to white
+ CGContextSetBlendMode( m_cgContext, kCGBlendModeExclusion );
+ CGContextSetShouldAntialias( m_cgContext, false );
+ retval = true;
+ }
+#endif
+ }
+
+ if (retval)
+ m_logicalFunction = function;
+ return retval ;
+}
void wxMacCoreGraphicsContext::Clip( const wxRegion ®ion )
{
}
else
{
- m_clipRgn.Set(HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() ));
+ // this offsetting to device coords is not really correct, but since we cannot apply affine transforms
+ // to regions we try at least to have correct translations
+ wxMacCFRefHolder<HIShapeRef> hishape ;
+ hishape.Set( HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() ));
+ HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( hishape );
+
+ CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform );
+ HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y );
+ m_clipRgn.Set(mutableShape);
}
}
}
else
{
+ // the clipping itself must be stored as device coordinates, otherwise
+ // we cannot apply it back correctly
+ r.origin= CGPointApplyAffineTransform( r.origin, m_windowTransform );
m_clipRgn.Set(HIShapeCreateWithRect(&r));
}
}
{
if ( m_cgContext )
{
+ // there is no way for clearing the clip, we can only revert to the stored
+ // state, but then we have to make sure everything else is NOT restored
+ CGAffineTransform transform = CGContextGetCTM( m_cgContext );
CGContextRestoreGState( m_cgContext );
CGContextSaveGState( m_cgContext );
+ CGAffineTransform transformNew = CGContextGetCTM( m_cgContext );
+ transformNew = CGAffineTransformInvert( transformNew ) ;
+ CGContextConcatCTM( m_cgContext, transformNew);
+ CGContextConcatCTM( m_cgContext, transform);
}
else
{
CGImageRef image = (CGImageRef)( bmp.CGImageCreate() );
HIRect r = CGRectMake( x , y , w , h );
- HIViewDrawCGImage( m_cgContext , &r , image );
+ if ( bmp.GetDepth() == 1 )
+ {
+ // is is a mask, the '1' in the mask tell where to draw the current brush
+ if ( !m_brush.IsNull() )
+ {
+ if ( ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->IsShading() )
+ {
+ // TODO clip to mask
+ /*
+ CGContextSaveGState( m_cgContext );
+ CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() );
+ CGContextClip( m_cgContext );
+ CGContextDrawShading( m_cgContext, ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->GetShading() );
+ CGContextRestoreGState( m_cgContext);
+ */
+ }
+ else
+ {
+ ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this);
+ HIViewDrawCGImage( m_cgContext , &r , image );
+ }
+ }
+ }
+ else
+ {
+ HIViewDrawCGImage( m_cgContext , &r , image );
+ }
CGImageRelease( image );
}
wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
Rect rect;
-/*
- // TODO
- if ( m_backgroundMode == wxSOLID )
- {
- wxGraphicsPath* path = m_graphicContext->CreatePath();
- path->MoveToPoint( drawX , drawY );
- path->AddLineToPoint(
- (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent)) ,
- (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent)) );
- path->AddLineToPoint(
- (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
- (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent) - sin(angle / RAD2DEG) * FixedToInt(textAfter)) );
- path->AddLineToPoint(
- (int) (drawX + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ,
- (int) (drawY - sin(angle / RAD2DEG) * FixedToInt(textAfter)) );
-
- m_graphicContext->FillPath( path , m_textBackgroundColour );
- delete path;
- }
-*/
- x += (int)(sin(angle / RAD2DEG) * FixedToInt(ascent));
- y += (int)(cos(angle / RAD2DEG) * FixedToInt(ascent));
+ x += (int)(sin(angle) * FixedToInt(ascent));
+ y += (int)(cos(angle) * FixedToInt(ascent));
status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
IntToFixed(x) , IntToFixed(y) , &rect );
*width = FixedToInt(textAfter - textBefore);
::ATSUDisposeTextLayout(atsuLayout);
+#if SIZEOF_WCHAR_T == 4
+ free( ubuf ) ;
+#endif
}
void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const
}
::ATSUDisposeTextLayout(atsuLayout);
+#if SIZEOF_WCHAR_T == 4
+ free( ubuf ) ;
+#endif
}
void * wxMacCoreGraphicsContext::GetNativeContext()
virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window );
virtual wxGraphicsContext * CreateContext( wxWindow* window );
+
+ virtual wxGraphicsContext * CreateMeasuringContext();
// Path
wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc)
{
- return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
+ wxMemoryDC* mdc = wxDynamicCast(&dc, wxMemoryDC);
+ if ( mdc )
+ {
+ return new wxMacCoreGraphicsContext(this,
+ (CGContextRef)mdc->GetGraphicsContext()->GetNativeContext());
+ }
+ else
+ {
+ return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() );
+ }
}
wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context )
return new wxMacCoreGraphicsContext(this, window );
}
+wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext()
+{
+ return new wxMacCoreGraphicsContext(this);
+}
+
// Path
wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath()