X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a7868cdf6a8782a04a46791dd63de2ade825a8bc..b724bafee0cbbb5c587d11e82a18c8ea5b060f26:/src/mac/carbon/graphics.cpp diff --git a/src/mac/carbon/graphics.cpp b/src/mac/carbon/graphics.cpp index a79c96bfc9..b2bcb0788a 100755 --- a/src/mac/carbon/graphics.cpp +++ b/src/mac/carbon/graphics.cpp @@ -17,6 +17,7 @@ #ifndef WX_PRECOMP #include "wx/dcclient.h" + #include "wx/dcmemory.h" #include "wx/log.h" #include "wx/region.h" #endif @@ -37,6 +38,13 @@ #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 @@ -161,7 +169,7 @@ public : 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 ); } @@ -395,7 +403,7 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer 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; @@ -407,7 +415,7 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer { 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; @@ -450,12 +458,19 @@ void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context ) 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 ); } } @@ -523,15 +538,38 @@ wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* rende 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; @@ -549,7 +587,7 @@ wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* rende 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 ) ) ) ); } } } @@ -582,11 +620,14 @@ void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext* context ) 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 ); } @@ -714,6 +755,10 @@ public : 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(); @@ -785,6 +830,18 @@ void wxMacCoreGraphicsMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDoub 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() { @@ -796,7 +853,7 @@ bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData* t) const { const CGAffineTransform* tm = (CGAffineTransform*) t->GetNativeMatrix(); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if ( CGAffineTransformEqualToTransform ) + if ( CGAffineTransformEqualToTransform!=NULL ) { return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix())); } @@ -1050,7 +1107,7 @@ void wxMacCoreGraphicsPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wx bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, int fillStyle) const { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if ( CGPathContainsPoint ) + if ( CGPathContainsPoint!=NULL ) { return CGPathContainsPoint( m_path, NULL, CGPointMake(x,y), fillStyle == wxODDEVEN_RULE ); } @@ -1105,6 +1162,7 @@ public: virtual void * GetNativeContext(); + bool SetLogicalFunction( int function ); // // transformation // @@ -1140,7 +1198,7 @@ public: virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE ); virtual bool ShouldOffset() const - { + { int penwidth = 0 ; if ( !m_pen.IsNull() ) { @@ -1270,13 +1328,55 @@ void wxMacCoreGraphicsContext::EnsureIsValid() 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 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 ) { @@ -1289,7 +1389,15 @@ 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 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); } } @@ -1303,6 +1411,9 @@ void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDoubl } 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)); } } @@ -1494,7 +1605,33 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDo 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 ); } @@ -1620,28 +1757,8 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub 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 ); @@ -1720,6 +1837,9 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid *width = FixedToInt(textAfter - textBefore); ::ATSUDisposeTextLayout(atsuLayout); +#if SIZEOF_WCHAR_T == 4 + free( ubuf ) ; +#endif } void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const @@ -1778,6 +1898,9 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr } ::ATSUDisposeTextLayout(atsuLayout); +#if SIZEOF_WCHAR_T == 4 + free( ubuf ) ; +#endif } void * wxMacCoreGraphicsContext::GetNativeContext() @@ -1843,6 +1966,8 @@ public : virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window ); virtual wxGraphicsContext * CreateContext( wxWindow* window ); + + virtual wxGraphicsContext * CreateMeasuringContext(); // Path @@ -1889,7 +2014,16 @@ wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer() 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 ) @@ -1908,6 +2042,11 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( wxWindow* window ) return new wxMacCoreGraphicsContext(this, window ); } +wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext() +{ + return new wxMacCoreGraphicsContext(this); +} + // Path wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath()