X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a7868cdf6a8782a04a46791dd63de2ade825a8bc..cd66beb3439485e49fac308f54dc10fe01c92895:/src/mac/carbon/graphics.cpp diff --git a/src/mac/carbon/graphics.cpp b/src/mac/carbon/graphics.cpp old mode 100755 new mode 100644 index a79c96bfc9..0766f67236 --- a/src/mac/carbon/graphics.cpp +++ b/src/mac/carbon/graphics.cpp @@ -11,14 +11,15 @@ #include "wx/wxprec.h" -#if wxUSE_GRAPHICS_CONTEXT && wxMAC_USE_CORE_GRAPHICS - #include "wx/graphics.h" #ifndef WX_PRECOMP #include "wx/dcclient.h" + #include "wx/dcmemory.h" #include "wx/log.h" #include "wx/region.h" + #include "wx/image.h" + #include "wx/icon.h" #endif #include "wx/mac/uma.h" @@ -34,10 +35,6 @@ #include "wx/mac/private.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 -typedef float CGFloat; -#endif - //----------------------------------------------------------------------------- // constants //----------------------------------------------------------------------------- @@ -57,6 +54,20 @@ static const double RAD2DEG = 180.0 / M_PI; #pragma mark - #pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes +OSStatus wxMacDrawCGImage( + CGContextRef inContext, + const HIRect * inBounds, + CGImageRef inImage) +{ +#ifdef __LP64__ + // todo flip + CGContextDrawImage(inContext, *inBounds, inImage ); + return noErr; +#else + return HIViewDrawCGImage( inContext, inBounds, inImage ); +#endif +} + // CGPattern wrapper class: always allocate on heap, never call destructor class wxMacCoreGraphicsPattern @@ -103,7 +114,7 @@ public : { wxASSERT( bmp && bmp->Ok() ); - Init( (CGImageRef) bmp->CGImageCreate() , transform ); + Init( (CGImageRef) bmp->CreateCGImage() , transform ); } // ImagePattern takes ownership of CGImageRef passed in @@ -118,7 +129,7 @@ public : virtual void Render( CGContextRef ctxRef ) { if (m_image != NULL) - HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image ); + wxMacDrawCGImage( ctxRef, &m_imageBounds, m_image ); } protected : @@ -160,22 +171,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 ) - { - CGContextStrokeLineSegments( ctxRef , pts , count ); - } - else -#endif - { - CGContextBeginPath( ctxRef ); - for (size_t i = 0; i < count; i += 2) - { - CGContextMoveToPoint(ctxRef, pts[i].x, pts[i].y); - CGContextAddLineToPoint(ctxRef, pts[i+1].x, pts[i+1].y); - } - CGContextStrokePath(ctxRef); - } + CGContextStrokeLineSegments( ctxRef , pts , count ); } virtual void Render( CGContextRef ctxRef ) @@ -289,7 +285,7 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer { Init(); - float components[4] = { pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 , + CGFloat components[4] = { pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 , pen.GetColour().Blue() / 255.0 , pen.GetColour().Alpha() / 255.0 } ; m_color.Set( CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ) ; @@ -395,7 +391,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 +403,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 +446,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 ); } } @@ -463,6 +466,105 @@ void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context ) // Brush // +static const char *gs_stripedback_xpm[] = { +/* columns rows colors chars-per-pixel */ +"4 4 2 1", +". c #F0F0F0", +"X c #ECECEC", +/* pixels */ +"....", +"....", +"XXXX", +"XXXX" +}; + +wxBitmap gs_stripedback_bmp( wxImage( (const char* const* ) gs_stripedback_xpm ), -1 ) ; + +// make sure we all use one class for all conversions from wx to native colour + +class wxMacCoreGraphicsColour +{ + public: + wxMacCoreGraphicsColour(); + wxMacCoreGraphicsColour(const wxBrush &brush); + ~wxMacCoreGraphicsColour(); + + void Apply( CGContextRef cgContext ); + protected: + void Init(); + wxMacCFRefHolder m_color; + wxMacCFRefHolder m_colorSpace; + + bool m_isPattern; + wxMacCFRefHolder m_pattern; + CGFloat* m_patternColorComponents; +} ; + +wxMacCoreGraphicsColour::~wxMacCoreGraphicsColour() +{ + delete[] m_patternColorComponents; +} + +void wxMacCoreGraphicsColour::Init() +{ + m_isPattern = false; + m_patternColorComponents = NULL; +} + +void wxMacCoreGraphicsColour::Apply( CGContextRef cgContext ) +{ + if ( m_isPattern ) + { + CGAffineTransform matrix = CGContextGetCTM( cgContext ); + CGContextSetPatternPhase( cgContext, CGSizeMake(matrix.tx, matrix.ty) ); + CGContextSetFillColorSpace( cgContext , m_colorSpace ); + CGContextSetFillPattern( cgContext, m_pattern , m_patternColorComponents ); + } + else + { + CGContextSetFillColorWithColor( cgContext, m_color ); + } +} + +wxMacCoreGraphicsColour::wxMacCoreGraphicsColour() +{ + Init(); +} + +wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush &brush ) +{ + Init(); + if ( brush.GetStyle() == wxSOLID ) + { + m_color.Set( brush.GetColour().CreateCGColor() ); + } + else if ( brush.IsHatch() ) + { + m_isPattern = true; + m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ); + 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[1] = brush.GetColour().Green() / 255.0; + m_patternColorComponents[2] = brush.GetColour().Blue() / 255.0; + m_patternColorComponents[3] = brush.GetColour().Alpha() / 255.0; + } + else + { + // now brush is a bitmap + wxBitmap* bmp = brush.GetStipple(); + if ( bmp && bmp->Ok() ) + { + m_isPattern = true; + m_patternColorComponents = new CGFloat[1] ; + m_patternColorComponents[0] = 1.0; + m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) ); + m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) ); + } + } +} + class wxMacCoreGraphicsBrushData : public wxGraphicsObjectRefData { public: @@ -483,12 +585,7 @@ protected: static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out); virtual void Init(); - wxMacCFRefHolder m_color; - wxMacCFRefHolder m_colorSpace; - - bool m_isPattern; - wxMacCFRefHolder m_pattern; - CGFloat* m_patternColorComponents; + wxMacCoreGraphicsColour m_cgColor; bool m_isShading; CGFunctionRef m_gradientFunction; @@ -517,41 +614,11 @@ void wxMacCoreGraphicsBrushData::CreateRadialGradientBrush( wxDouble xo, wxDoubl m_isShading = true ; } -wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* renderer, const wxBrush &brush) : wxGraphicsObjectRefData( renderer ) +wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* renderer, const wxBrush &brush) : wxGraphicsObjectRefData( renderer ), + m_cgColor( brush ) { Init(); - if ( brush.GetStyle() == wxSOLID ) - { - 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 ) ) ; - } - else if ( brush.IsHatch() ) - { - m_isPattern = true; - m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ); - m_pattern.Set( *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeTranslation( 0,0 ) ) ) ); - - m_patternColorComponents = new CGFloat[4] ; - m_patternColorComponents[0] = brush.GetColour().Red() / 255.0; - m_patternColorComponents[1] = brush.GetColour().Green() / 255.0; - m_patternColorComponents[2] = brush.GetColour().Blue() / 255.0; - m_patternColorComponents[3] = brush.GetColour().Alpha() / 255.0; - } - else - { - // now brush is a bitmap - wxBitmap* bmp = brush.GetStipple(); - if ( bmp && bmp->Ok() ) - { - m_isPattern = true; - m_patternColorComponents = new CGFloat[1] ; - m_patternColorComponents[0] = 1.0; - m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) ); - m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeTranslation( 0,0 ) ) ) ); - } - } } wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData() @@ -563,15 +630,12 @@ wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData() CGFunctionRelease(m_gradientFunction); delete[] m_gradientComponents; - delete[] m_patternColorComponents; } void wxMacCoreGraphicsBrushData::Init() { - m_patternColorComponents = NULL; m_gradientFunction = NULL; m_shading = NULL; - m_isPattern = false; m_gradientComponents = NULL; m_isShading = false; } @@ -582,18 +646,11 @@ 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 ) - { - CGContextSetFillColorSpace( cg , m_colorSpace ); - CGContextSetFillPattern( cg, m_pattern , m_patternColorComponents ); - } - else - { - CGContextSetFillColorWithColor( cg, m_color ); - } + m_cgColor.Apply( cg ); } } @@ -648,6 +705,8 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere { m_macATSUIStyle = NULL; +#ifdef wxMAC_USE_CORE_TEXT +#elif defined(wxMAC_USE_ATSU_TEXT) OSStatus status; status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle ); @@ -657,7 +716,8 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere // we need the scale here ... Fixed atsuSize = IntToFixed( int( 1 * font.MacGetFontSize()) ); - RGBColor atsuColor = MAC_WXCOLORREF( col.GetPixel() ); + RGBColor atsuColor ; + col.GetRGBColor( &atsuColor ); ATSUAttributeTag atsuTags[] = { kATSUSizeTag , @@ -679,15 +739,21 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere atsuTags, atsuSizes, atsuValues); wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") ); +#elif defined(WXMAC_USE_CG_TEXT) +#endif } wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData() { +#ifdef wxMAC_USE_CORE_TEXT +#elif defined(wxMAC_USE_ATSU_TEXT) if ( m_macATSUIStyle ) { ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle); m_macATSUIStyle = NULL; } +#elif defined(WXMAC_USE_CG_TEXT) +#endif } // @@ -714,6 +780,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 +855,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() { @@ -794,23 +876,7 @@ void wxMacCoreGraphicsMatrixData::Invert() // returns true if the elements of the transformation matrix are equal ? 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 ) - { - 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 CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix())); } // return true if this is the identity matrix @@ -928,7 +994,7 @@ public : virtual void * GetNativePath() const { return m_path; } // give the native path returned by GetNativePath() back (there might be some deallocations necessary) - virtual void UnGetNativePath(void *p) const {} + virtual void UnGetNativePath(void *WXUNUSED(p)) const {} // transforms each point of this path by the matrix virtual void Transform( const wxGraphicsMatrixData* matrix ); @@ -1049,18 +1115,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 ) - { - 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; - } + return CGPathContainsPoint( m_path, NULL, CGPointMake(x,y), fillStyle == wxODDEVEN_RULE ); } // @@ -1074,7 +1129,7 @@ bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, int fillStyle) class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext { public: - wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext ); + wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width = 0, wxDouble height = 0 ); wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ); @@ -1088,6 +1143,15 @@ public: void Init(); + // returns the size of the graphics context in device coordinates + virtual void GetSize( wxDouble* width, wxDouble* height); + + virtual void StartPage( wxDouble width, wxDouble height ); + + virtual void EndPage(); + + virtual void Flush(); + // push the current state of the context, ie the transformation matrix on a stack virtual void PushState(); @@ -1105,6 +1169,7 @@ public: virtual void * GetNativeContext(); + bool SetLogicalFunction( int function ); // // transformation // @@ -1140,7 +1205,7 @@ public: virtual void DrawPath( const wxGraphicsPath &path, int fillStyle = wxODDEVEN_RULE ); virtual bool ShouldOffset() const - { + { int penwidth = 0 ; if ( !m_pen.IsNull() ) { @@ -1183,6 +1248,8 @@ private: WindowRef m_windowRef; bool m_releaseContext; CGAffineTransform m_windowTransform; + wxDouble m_width; + wxDouble m_height; wxMacCFRefHolder m_clipRgn; }; @@ -1205,20 +1272,44 @@ private: IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext) +class wxQuartzOffsetHelper +{ +public : + wxQuartzOffsetHelper( CGContextRef cg , bool offset ) + { + m_cg = cg; + m_offset = offset; + if ( m_offset ) + CGContextTranslateCTM( m_cg, 0.5, 0.5 ); + } + ~wxQuartzOffsetHelper( ) + { + if ( m_offset ) + CGContextTranslateCTM( m_cg, -0.5, -0.5 ); + } +public : + CGContextRef m_cg; + bool m_offset; +} ; + void wxMacCoreGraphicsContext::Init() { m_cgContext = NULL; m_releaseContext = false; m_windowRef = NULL; + m_width = 0; + m_height = 0; HIRect r = CGRectMake(0,0,0,0); m_clipRgn.Set(HIShapeCreateWithRect(&r)); } -wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext ) : wxGraphicsContext(renderer) +wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer) { Init(); SetNativeContext(cgcontext); + m_width = width; + m_height = height; } wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer) @@ -1234,9 +1325,12 @@ wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer int originX , originY; originX = originY = 0; window->MacWindowToRootWindow( &originX , &originY ); - Rect bounds; - GetWindowBounds( m_windowRef, kWindowContentRgn, &bounds ); + Rect bounds = { 0,0,0,0 }; +#ifdef __LP64__ +#else + GetWindowBounds( m_windowRef, kWindowContentRgn, &bounds ); +#endif m_windowTransform = CGAffineTransformMakeTranslation( 0 , bounds.bottom - bounds.top ); m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 ); m_windowTransform = CGAffineTransformTranslate( m_windowTransform, originX, originY ) ; @@ -1258,11 +1352,46 @@ wxMacCoreGraphicsContext::~wxMacCoreGraphicsContext() SetNativeContext(NULL); } +void wxMacCoreGraphicsContext::GetSize( wxDouble* width, wxDouble* height) +{ + *width = m_width; + *height = m_height; +} + + +void wxMacCoreGraphicsContext::StartPage( wxDouble width, wxDouble height ) +{ + CGRect r; + if ( width != 0 && height != 0) + r = CGRectMake( 0 , 0 , width , height ); + else + r = CGRectMake( 0 , 0 , m_width , m_height ); + + CGContextBeginPage(m_cgContext, &r ); +// CGContextTranslateCTM( m_cgContext , 0 , height == 0 ? m_height : height ); +// CGContextScaleCTM( m_cgContext , 1 , -1 ); +} + +void wxMacCoreGraphicsContext::EndPage() +{ + CGContextEndPage(m_cgContext); +} + +void wxMacCoreGraphicsContext::Flush() +{ + CGContextFlush(m_cgContext); +} + void wxMacCoreGraphicsContext::EnsureIsValid() { if ( !m_cgContext ) { - OSStatus status = QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext ); + OSStatus status = +#ifndef __LP64__ + QDBeginCGContext( GetWindowPort( m_windowRef ) , &m_cgContext ); +#else + paramErr; +#endif wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") ); CGContextConcatCTM( m_cgContext, m_windowTransform ); @@ -1270,26 +1399,63 @@ 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 ); } } +// TODO test whether the private CGContextSetCompositeOperation works under 10.3 (using NSCompositingModes) + +bool wxMacCoreGraphicsContext::SetLogicalFunction( int function ) +{ + if (m_logicalFunction == function) + return true; + + EnsureIsValid(); + + bool retval = false; + + if ( function == wxCOPY ) + { + retval = true; + CGContextSetBlendMode( m_cgContext, kCGBlendModeNormal ); + } + else if ( function == wxINVERT || function == wxXOR ) + { + // change color to white + CGContextSetBlendMode( m_cgContext, kCGBlendModeExclusion ); + CGContextSetShouldAntialias( m_cgContext, false ); + retval = true; + } + + if (retval) + m_logicalFunction = function; + return retval ; +} void wxMacCoreGraphicsContext::Clip( const wxRegion ®ion ) { if( m_cgContext ) { - HIShapeRef shape = HIShapeCreateWithQDRgn( (RgnHandle) region.GetWXHRGN() ); - HIShapeReplacePathInCGContext( shape, m_cgContext ); + HIShapeReplacePathInCGContext( region.GetWXHRGN() , m_cgContext ); CGContextClip( m_cgContext ); - CFRelease( shape ); } 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 + HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( region.GetWXHRGN() ); + + CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform ); + HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y ); + m_clipRgn.Set(mutableShape); } } @@ -1303,6 +1469,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)); } } @@ -1336,16 +1505,11 @@ void wxMacCoreGraphicsContext::StrokePath( const wxGraphicsPath &path ) EnsureIsValid(); - bool offset = ShouldOffset(); - if ( offset ) - CGContextTranslateCTM( m_cgContext, 0.5, 0.5 ); + wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() ); ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this); CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() ); CGContextStrokePath( m_cgContext ); - - if ( offset ) - CGContextTranslateCTM( m_cgContext, -0.5, -0.5 ); } void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillStyle ) @@ -1391,16 +1555,10 @@ void wxMacCoreGraphicsContext::DrawPath( const wxGraphicsPath &path , int fillSt if ( !m_pen.IsNull() ) ((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->Apply(this); - bool offset = ShouldOffset(); - - if ( offset ) - CGContextTranslateCTM( m_cgContext, 0.5, 0.5 ); + wxQuartzOffsetHelper helper( m_cgContext , ShouldOffset() ); CGContextAddPath( m_cgContext , (CGPathRef) path.GetNativePath() ); CGContextDrawPath( m_cgContext , mode ); - - if ( offset ) - CGContextTranslateCTM( m_cgContext, -0.5, -0.5 ); } void wxMacCoreGraphicsContext::FillPath( const wxGraphicsPath &path , int fillStyle ) @@ -1440,7 +1598,11 @@ void wxMacCoreGraphicsContext::SetNativeContext( CGContextRef cg ) CGContextRestoreGState( m_cgContext ); CGContextRestoreGState( m_cgContext ); if ( m_releaseContext ) + { +#ifndef __LP64__ QDEndCGContext( GetWindowPort( m_windowRef ) , &m_cgContext); +#endif + } else CGContextRelease(m_cgContext); } @@ -1492,9 +1654,35 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDo { EnsureIsValid(); - CGImageRef image = (CGImageRef)( bmp.CGImageCreate() ); + CGImageRef image = (CGImageRef)( bmp.CreateCGImage() ); 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); + wxMacDrawCGImage( m_cgContext , &r , image ); + } + } + } + else + { + wxMacDrawCGImage( m_cgContext , &r , image ); + } CGImageRelease( image ); } @@ -1527,7 +1715,17 @@ void wxMacCoreGraphicsContext::PopState() void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y ) { + if ( m_font.IsNull() ) + return; + + EnsureIsValid(); +#ifdef wxMAC_USE_CORE_TEXT + // TODO core text implementation here +#elif defined(wxMAC_USE_ATSU_TEXT) DrawText(str, x, y, 0.0); +#elif defined(WXMAC_USE_CG_TEXT) + // TODO core graphics text implementation here +#endif } void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle ) @@ -1536,7 +1734,10 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub return; EnsureIsValid(); - +#ifdef wxMAC_USE_CORE_TEXT + // default implementation takes care of rotation and calls non rotated DrawText afterwards + wxGraphicsContext::DrawText( str, x, y, angle ); +#elif defined(wxMAC_USE_ATSU_TEXT) OSStatus status = noErr; ATSUTextLayout atsuLayout; UniCharCount chars = str.length(); @@ -1620,28 +1821,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 ); @@ -1662,6 +1843,10 @@ void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDoub #if SIZEOF_WCHAR_T == 4 free( ubuf ); #endif +#elif defined(WXMAC_USE_CG_TEXT) + // default implementation takes care of rotation and calls non rotated DrawText afterwards + wxGraphicsContext::DrawText( str, x, y, angle ); +#endif } void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *width, wxDouble *height, @@ -1669,6 +1854,21 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid { wxCHECK_RET( !m_font.IsNull(), wxT("wxDC(cg)::DoGetTextExtent - no valid font set") ); + if ( width ) + *width = 0; + if ( height ) + *height = 0; + if ( descent ) + *descent = 0; + if ( externalLeading ) + *externalLeading = 0; + + if (str.empty()) + return; + +#ifdef wxMAC_USE_CORE_TEXT + // TODO core text implementation here +#elif defined(wxMAC_USE_ATSU_TEXT) OSStatus status = noErr; ATSUTextLayout atsuLayout; @@ -1720,6 +1920,12 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid *width = FixedToInt(textAfter - textBefore); ::ATSUDisposeTextLayout(atsuLayout); +#if SIZEOF_WCHAR_T == 4 + free( ubuf ) ; +#endif +#elif defined(WXMAC_USE_CG_TEXT) + // TODO core graphics text implementation here +#endif } void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const @@ -1730,6 +1936,9 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr if (text.empty()) return; +#ifdef wxMAC_USE_CORE_TEXT + // TODO core text implementation here +#elif defined(wxMAC_USE_ATSU_TEXT) ATSUTextLayout atsuLayout; UniCharCount chars = text.length(); UniChar* ubuf = NULL; @@ -1778,6 +1987,12 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr } ::ATSUDisposeTextLayout(atsuLayout); +#if SIZEOF_WCHAR_T == 4 + free( ubuf ) ; +#endif +#elif defined(WXMAC_USE_CG_TEXT) + // TODO core graphics text implementation here +#endif } void * wxMacCoreGraphicsContext::GetNativeContext() @@ -1843,6 +2058,8 @@ public : virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window ); virtual wxGraphicsContext * CreateContext( wxWindow* window ); + + virtual wxGraphicsContext * CreateMeasuringContext(); // Path @@ -1889,7 +2106,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 +2134,11 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( wxWindow* window ) return new wxMacCoreGraphicsContext(this, window ); } +wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext() +{ + return new wxMacCoreGraphicsContext(this); +} + // Path wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath() @@ -1990,6 +2221,3 @@ wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const return wxNullGraphicsFont; } - - -#endif // wxMAC_USE_CORE_GRAPHICS