X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e1673e527f08395de6864b09540162ca409a3c28..4813bb8d72d4e6821e031f2b19baaa338b714d39:/src/mac/carbon/graphics.cpp?ds=sidebyside diff --git a/src/mac/carbon/graphics.cpp b/src/mac/carbon/graphics.cpp index 31be96bbef..616c5d4a54 100644 --- a/src/mac/carbon/graphics.cpp +++ b/src/mac/carbon/graphics.cpp @@ -12,6 +12,7 @@ #include "wx/wxprec.h" #include "wx/graphics.h" +#include "wx/private/graphics.h" #ifndef WX_PRECOMP #include "wx/dcclient.h" @@ -19,6 +20,7 @@ #include "wx/log.h" #include "wx/region.h" #include "wx/image.h" + #include "wx/icon.h" #endif #include "wx/mac/uma.h" @@ -34,10 +36,6 @@ #include "wx/mac/private.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 -typedef float CGFloat; -#endif - //----------------------------------------------------------------------------- // constants //----------------------------------------------------------------------------- @@ -57,6 +55,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 +115,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 +130,7 @@ public : virtual void Render( CGContextRef ctxRef ) { if (m_image != NULL) - HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image ); + wxMacDrawCGImage( ctxRef, &m_imageBounds, m_image ); } protected : @@ -253,8 +265,8 @@ public: protected : CGLineCap m_cap; - wxMacCFRefHolder m_color; - wxMacCFRefHolder m_colorSpace; + wxCFRef m_color; + wxCFRef m_colorSpace; CGLineJoin m_join; CGFloat m_width; @@ -265,7 +277,7 @@ protected : bool m_isPattern; - wxMacCFRefHolder m_pattern; + wxCFRef m_pattern; CGFloat* m_patternColorComponents; }; @@ -274,9 +286,7 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer { Init(); - 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 ) ) ; + m_color.reset( pen.GetColour().CreateCGColor() ) ; // TODO: * m_dc->m_scaleX m_width = pen.GetWidth(); @@ -379,8 +389,8 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer wxBitmap* bmp = pen.GetStipple(); if ( bmp && bmp->Ok() ) { - m_colorSpace.Set( CGColorSpaceCreatePattern( NULL ) ); - m_pattern.Set( *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) ); + m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) ); + m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) ); m_patternColorComponents = new CGFloat[1] ; m_patternColorComponents[0] = 1.0; m_isPattern = true; @@ -391,8 +401,8 @@ wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer default : { m_isPattern = true; - m_colorSpace.Set( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ); - m_pattern.Set( *( new HatchPattern( pen.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) ); + m_colorSpace.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ); + m_pattern.reset( (CGPatternRef) *( 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; @@ -469,6 +479,26 @@ static const char *gs_stripedback_xpm[] = { 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(); + wxCFRef m_color; + wxCFRef m_colorSpace; + + bool m_isPattern; + wxCFRef m_pattern; + CGFloat* m_patternColorComponents; +} ; + wxMacCoreGraphicsColour::~wxMacCoreGraphicsColour() { delete[] m_patternColorComponents; @@ -505,24 +535,13 @@ wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush &brush ) Init(); if ( brush.GetStyle() == wxSOLID ) { - if ( brush.MacGetBrushKind() == kwxMacBrushTheme ) - { - CGColorRef color ; - HIThemeBrushCreateCGColor( brush.MacGetTheme(), &color ); - m_color.Set( color ) ; - } - else - { - CGFloat 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.reset( 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_colorSpace.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ); + m_pattern.reset( (CGPatternRef) *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) ); m_patternColorComponents = new CGFloat[4] ; m_patternColorComponents[0] = brush.GetColour().Red() / 255.0; @@ -539,8 +558,8 @@ wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush &brush ) 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 ) ) ) ); + m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) ); + m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) ); } } } @@ -676,16 +695,37 @@ public: wxMacCoreGraphicsFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col ); ~wxMacCoreGraphicsFontData(); +#if wxMAC_USE_ATSU_TEXT virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; } +#endif +#if wxMAC_USE_CORE_TEXT + CTFontRef GetCTFont() const { return m_ctFont ; } +#endif + wxColour GetColour() const { return m_colour ; } + + bool GetUnderlined() const { return m_underlined ; } private : + wxColour m_colour; + bool m_underlined; +#if wxMAC_USE_ATSU_TEXT ATSUStyle m_macATSUIStyle; +#endif +#if wxMAC_USE_CORE_TEXT + wxCFRef< CTFontRef > m_ctFont; +#endif }; wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsObjectRefData( renderer ) { - m_macATSUIStyle = NULL; + m_colour = col; + m_underlined = font.GetUnderlined(); - OSStatus status; +#if wxMAC_USE_CORE_TEXT + m_ctFont.reset( wxCFRetain((CTFontRef) font.MacGetCTFont()) ); +#endif +#if wxMAC_USE_ATSU_TEXT + OSStatus status = noErr; + m_macATSUIStyle = NULL; status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle ); @@ -694,7 +734,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 , @@ -716,15 +757,24 @@ wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* rendere atsuTags, atsuSizes, atsuValues); wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") ); +#endif +#if wxMAC_USE_CG_TEXT +#endif } wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData() { +#if wxMAC_USE_CORE_TEXT +#endif +#if wxMAC_USE_ATSU_TEXT if ( m_macATSUIStyle ) { ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle); m_macATSUIStyle = NULL; } +#endif +#if wxMAC_USE_CG_TEXT +#endif } // @@ -1222,7 +1272,7 @@ private: wxDouble m_width; wxDouble m_height; - wxMacCFRefHolder m_clipRgn; + wxCFRef m_clipRgn; }; //----------------------------------------------------------------------------- @@ -1272,7 +1322,7 @@ void wxMacCoreGraphicsContext::Init() m_height = 0; HIRect r = CGRectMake(0,0,0,0); - m_clipRgn.Set(HIShapeCreateWithRect(&r)); + m_clipRgn.reset(HIShapeCreateWithRect(&r)); } wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer) @@ -1296,9 +1346,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 ) ; @@ -1368,8 +1421,7 @@ void wxMacCoreGraphicsContext::EnsureIsValid() if ( !HIShapeIsEmpty(m_clipRgn) ) { // the clip region is in device coordinates, so we convert this again to user coordinates - wxMacCFRefHolder hishape ; - hishape.Set( HIShapeCreateMutableCopy( m_clipRgn ) ); + wxCFRef hishape( HIShapeCreateMutableCopy( m_clipRgn ) ); CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero,m_windowTransform); HIShapeOffset( hishape, -transformedOrigin.x, -transformedOrigin.y ); HIShapeReplacePathInCGContext( hishape, m_cgContext ); @@ -1389,22 +1441,53 @@ bool wxMacCoreGraphicsContext::SetLogicalFunction( int function ) EnsureIsValid(); bool retval = false; - - if ( function == wxCOPY ) + bool shouldAntiAlias = true; + CGBlendMode mode = kCGBlendModeNormal; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if ( UMAGetSystemVersion() >= 0x1050 ) { retval = true; - CGContextSetBlendMode( m_cgContext, kCGBlendModeNormal ); + switch ( function ) + { + // 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; + } } - else if ( function == wxINVERT || function == wxXOR ) + else +#endif { - // change color to white - CGContextSetBlendMode( m_cgContext, kCGBlendModeExclusion ); - CGContextSetShouldAntialias( m_cgContext, false ); - retval = true; + if ( function == wxCOPY ) + { + retval = true; + } + else if ( function == wxINVERT || function == wxXOR ) + { + // change color to white + mode = kCGBlendModeExclusion; + shouldAntiAlias = false; + retval = true; + } } if (retval) + { m_logicalFunction = function; + CGContextSetBlendMode( m_cgContext, mode ); + CGContextSetShouldAntialias(m_cgContext, shouldAntiAlias); + } return retval ; } @@ -1412,22 +1495,18 @@ 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 { // 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 ); + HIMutableShapeRef mutableShape = HIShapeCreateMutableCopy( region.GetWXHRGN() ); CGPoint transformedOrigin = CGPointApplyAffineTransform( CGPointZero, m_windowTransform ); HIShapeOffset( mutableShape, transformedOrigin.x, transformedOrigin.y ); - m_clipRgn.Set(mutableShape); + m_clipRgn.reset(mutableShape); } } @@ -1444,7 +1523,7 @@ void wxMacCoreGraphicsContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDoubl // 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)); + m_clipRgn.reset(HIShapeCreateWithRect(&r)); } } @@ -1466,7 +1545,7 @@ void wxMacCoreGraphicsContext::ResetClip() else { HIRect r = CGRectMake(0,0,0,0); - m_clipRgn.Set(HIShapeCreateWithRect(&r)); + m_clipRgn.reset(HIShapeCreateWithRect(&r)); } } @@ -1626,7 +1705,7 @@ 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 ); if ( bmp.GetDepth() == 1 ) { @@ -1647,13 +1726,13 @@ void wxMacCoreGraphicsContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDo else { ((wxMacCoreGraphicsBrushData*)m_brush.GetRefData())->Apply(this); - HIViewDrawCGImage( m_cgContext , &r , image ); + wxMacDrawCGImage( m_cgContext , &r , image ); } } } else { - HIViewDrawCGImage( m_cgContext , &r , image ); + wxMacDrawCGImage( m_cgContext , &r , image ); } CGImageRelease( image ); } @@ -1686,121 +1765,150 @@ void wxMacCoreGraphicsContext::PopState() } void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y ) -{ - DrawText(str, x, y, 0.0); -} - -void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle ) { if ( m_font.IsNull() ) return; - + EnsureIsValid(); - - OSStatus status = noErr; - ATSUTextLayout atsuLayout; - UniCharCount chars = str.length(); - UniChar* ubuf = NULL; - -#if SIZEOF_WCHAR_T == 4 - wxMBConvUTF16 converter; -#if wxUSE_UNICODE - size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ); - ubuf = (UniChar*) malloc( unicharlen + 2 ); - converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 ); -#else - const wxWCharBuffer wchar = str.wc_str( wxConvLocal ); - size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ); - ubuf = (UniChar*) malloc( unicharlen + 2 ); - converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ); +#if wxMAC_USE_CORE_TEXT + if ( UMAGetSystemVersion() >= 0x1050 ) + { + wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData(); + wxCFStringRef text(str, wxLocale::GetSystemEncoding() ); + CTFontRef font = fref->GetCTFont(); + CGColorRef col = fref->GetColour().GetPixel(); + CTUnderlineStyle ustyle = fref->GetUnderlined() ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone ; + wxCFRef underlined( CFNumberCreate(NULL, kCFNumberSInt32Type, &ustyle) ); + CFStringRef keys[] = { kCTFontAttributeName , kCTForegroundColorAttributeName, kCTUnderlineStyleAttributeName }; + CFTypeRef values[] = { font, col, underlined }; + wxCFRef attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values, + WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ); + wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) ); + wxCFRef line( CTLineCreateWithAttributedString(attrtext) ); + + y += CTFontGetAscent(font); + + CGContextSaveGState(m_cgContext); + CGContextTranslateCTM(m_cgContext, x, y); + CGContextScaleCTM(m_cgContext, 1, -1); + CGContextSetTextPosition(m_cgContext, 0, 0); + CTLineDraw( line, m_cgContext ); + CGContextRestoreGState(m_cgContext); + return; + } #endif - chars = unicharlen / 2; -#else -#if wxUSE_UNICODE - ubuf = (UniChar*) str.wc_str(); -#else - wxWCharBuffer wchar = str.wc_str( wxConvLocal ); - chars = wxWcslen( wchar.data() ); - ubuf = (UniChar*) wchar.data(); +#if wxMAC_USE_ATSU_TEXT + { + DrawText(str, x, y, 0.0); + return; + } #endif +#if wxMAC_USE_CG_TEXT + // TODO core graphics text implementation here #endif +} - ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle()); - status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 , - &chars , &style , &atsuLayout ); - - wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") ); - - status = ::ATSUSetTransientFontMatching( atsuLayout , true ); - wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") ); +void wxMacCoreGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle ) +{ + if ( m_font.IsNull() ) + return; - int iAngle = int( angle * RAD2DEG ); - if ( abs(iAngle) > 0 ) + EnsureIsValid(); +#if wxMAC_USE_CORE_TEXT + if ( UMAGetSystemVersion() >= 0x1050 ) { - Fixed atsuAngle = IntToFixed( iAngle ); - ATSUAttributeTag atsuTags[] = - { - kATSULineRotationTag , - }; - ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = - { - sizeof( Fixed ) , - }; - ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = - { - &atsuAngle , - }; - status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag), - atsuTags, atsuSizes, atsuValues ); + // default implementation takes care of rotation and calls non rotated DrawText afterwards + wxGraphicsContext::DrawText( str, x, y, angle ); + return; } - +#endif +#if wxMAC_USE_ATSU_TEXT { - ATSUAttributeTag atsuTags[] = - { - kATSUCGContextTag , - }; - ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = + OSStatus status = noErr; + ATSUTextLayout atsuLayout; + wxMacUniCharBuffer unibuf( str ); + UniCharCount chars = unibuf.GetChars(); + + ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle()); + status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 , + &chars , &style , &atsuLayout ); + + wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") ); + + status = ::ATSUSetTransientFontMatching( atsuLayout , true ); + wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") ); + + int iAngle = int( angle * RAD2DEG ); + if ( abs(iAngle) > 0 ) { - sizeof( CGContextRef ) , - }; - ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = + Fixed atsuAngle = IntToFixed( iAngle ); + ATSUAttributeTag atsuTags[] = + { + kATSULineRotationTag , + }; + ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = + { + sizeof( Fixed ) , + }; + ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = + { + &atsuAngle , + }; + status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag), + atsuTags, atsuSizes, atsuValues ); + } + { - &m_cgContext , - }; - status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag), - atsuTags, atsuSizes, atsuValues ); + ATSUAttributeTag atsuTags[] = + { + kATSUCGContextTag , + }; + ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = + { + sizeof( CGContextRef ) , + }; + ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = + { + &m_cgContext , + }; + status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags) / sizeof(ATSUAttributeTag), + atsuTags, atsuSizes, atsuValues ); + } + + ATSUTextMeasurement textBefore, textAfter; + ATSUTextMeasurement ascent, descent; + + status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, + &textBefore , &textAfter, &ascent , &descent ); + + wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") ); + + Rect rect; + x += (int)(sin(angle) * FixedToInt(ascent)); + y += (int)(cos(angle) * FixedToInt(ascent)); + + status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, + IntToFixed(x) , IntToFixed(y) , &rect ); + wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") ); + + CGContextSaveGState(m_cgContext); + CGContextTranslateCTM(m_cgContext, x, y); + CGContextScaleCTM(m_cgContext, 1, -1); + status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, + IntToFixed(0) , IntToFixed(0) ); + + wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") ); + + CGContextRestoreGState(m_cgContext); + + ::ATSUDisposeTextLayout(atsuLayout); + + return; } - - ATSUTextMeasurement textBefore, textAfter; - ATSUTextMeasurement ascent, descent; - - status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, - &textBefore , &textAfter, &ascent , &descent ); - - wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") ); - - Rect rect; - x += (int)(sin(angle) * FixedToInt(ascent)); - y += (int)(cos(angle) * FixedToInt(ascent)); - - status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, - IntToFixed(x) , IntToFixed(y) , &rect ); - wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") ); - - CGContextSaveGState(m_cgContext); - CGContextTranslateCTM(m_cgContext, x, y); - CGContextScaleCTM(m_cgContext, 1, -1); - status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, - IntToFixed(0) , IntToFixed(0) ); - - wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") ); - - CGContextRestoreGState(m_cgContext); - - ::ATSUDisposeTextLayout(atsuLayout); - -#if SIZEOF_WCHAR_T == 4 - free( ubuf ); +#endif +#if wxMAC_USE_CG_TEXT + // default implementation takes care of rotation and calls non rotated DrawText afterwards + wxGraphicsContext::DrawText( str, x, y, angle ); #endif } @@ -1821,59 +1929,71 @@ void wxMacCoreGraphicsContext::GetTextExtent( const wxString &str, wxDouble *wid if (str.empty()) return; - OSStatus status = noErr; - - ATSUTextLayout atsuLayout; - UniCharCount chars = str.length(); - UniChar* ubuf = NULL; - -#if SIZEOF_WCHAR_T == 4 - wxMBConvUTF16 converter; -#if wxUSE_UNICODE - size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ); - ubuf = (UniChar*) malloc( unicharlen + 2 ); - converter.WC2MB( (char*) ubuf , str.wc_str(), unicharlen + 2 ); -#else - const wxWCharBuffer wchar = str.wc_str( wxConvLocal ); - size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ); - ubuf = (UniChar*) malloc( unicharlen + 2 ); - converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ); -#endif - chars = unicharlen / 2; -#else -#if wxUSE_UNICODE - ubuf = (UniChar*) str.wc_str(); -#else - wxWCharBuffer wchar = str.wc_str( wxConvLocal ); - chars = wxWcslen( wchar.data() ); - ubuf = (UniChar*) wchar.data(); -#endif +#if wxMAC_USE_CORE_TEXT + if ( UMAGetSystemVersion() >= 0x1050 ) + { + wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData(); + CTFontRef font = fref->GetCTFont(); + + wxCFStringRef text(str, wxLocale::GetSystemEncoding() ); + CFStringRef keys[] = { kCTFontAttributeName }; + CFTypeRef values[] = { font }; + wxCFRef attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values, + WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ); + wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, text, attributes) ); + wxCFRef line( CTLineCreateWithAttributedString(attrtext) ); + + CGFloat w, a, d, l; + + w = CTLineGetTypographicBounds(line, &a, &d, &l) ; + + if ( height ) + *height = a+d+l; + if ( descent ) + *descent = d; + if ( externalLeading ) + *externalLeading = l; + if ( width ) + *width = w; + return; + } #endif +#if wxMAC_USE_ATSU_TEXT + { + OSStatus status = noErr; + + ATSUTextLayout atsuLayout; + wxMacUniCharBuffer unibuf( str ); + UniCharCount chars = unibuf.GetChars(); + + ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle()); + status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 , + &chars , &style , &atsuLayout ); + + wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") ); + + ATSUTextMeasurement textBefore, textAfter; + ATSUTextMeasurement textAscent, textDescent; + + status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, + &textBefore , &textAfter, &textAscent , &textDescent ); + + if ( height ) + *height = FixedToInt(textAscent + textDescent); + if ( descent ) + *descent = FixedToInt(textDescent); + if ( externalLeading ) + *externalLeading = 0; + if ( width ) + *width = FixedToInt(textAfter - textBefore); + + ::ATSUDisposeTextLayout(atsuLayout); - ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle()); - status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 , - &chars , &style , &atsuLayout ); - - wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") ); - - ATSUTextMeasurement textBefore, textAfter; - ATSUTextMeasurement textAscent, textDescent; - - status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, - &textBefore , &textAfter, &textAscent , &textDescent ); - - if ( height ) - *height = FixedToInt(textAscent + textDescent); - if ( descent ) - *descent = FixedToInt(textDescent); - if ( externalLeading ) - *externalLeading = 0; - if ( width ) - *width = FixedToInt(textAfter - textBefore); - - ::ATSUDisposeTextLayout(atsuLayout); -#if SIZEOF_WCHAR_T == 4 - free( ubuf ) ; + return; + } +#endif +#if wxMAC_USE_CG_TEXT + // TODO core graphics text implementation here #endif } @@ -1885,56 +2005,59 @@ void wxMacCoreGraphicsContext::GetPartialTextExtents(const wxString& text, wxArr if (text.empty()) return; - ATSUTextLayout atsuLayout; - UniCharCount chars = text.length(); - UniChar* ubuf = NULL; - -#if SIZEOF_WCHAR_T == 4 - wxMBConvUTF16 converter; -#if wxUSE_UNICODE - size_t unicharlen = converter.WC2MB( NULL , text.wc_str() , 0 ); - ubuf = (UniChar*) malloc( unicharlen + 2 ); - converter.WC2MB( (char*) ubuf , text.wc_str(), unicharlen + 2 ); -#else - const wxWCharBuffer wchar = text.wc_str( wxConvLocal ); - size_t unicharlen = converter.WC2MB( NULL , wchar.data() , 0 ); - ubuf = (UniChar*) malloc( unicharlen + 2 ); - converter.WC2MB( (char*) ubuf , wchar.data() , unicharlen + 2 ); -#endif - chars = unicharlen / 2; -#else -#if wxUSE_UNICODE - ubuf = (UniChar*) text.wc_str(); -#else - wxWCharBuffer wchar = text.wc_str( wxConvLocal ); - chars = wxWcslen( wchar.data() ); - ubuf = (UniChar*) wchar.data(); -#endif +#if wxMAC_USE_CORE_TEXT + { + wxMacCoreGraphicsFontData* fref = (wxMacCoreGraphicsFontData*)m_font.GetRefData(); + CTFontRef font = fref->GetCTFont(); + + wxCFStringRef t(text, wxLocale::GetSystemEncoding() ); + CFStringRef keys[] = { kCTFontAttributeName }; + CFTypeRef values[] = { font }; + wxCFRef attributes( CFDictionaryCreate(kCFAllocatorDefault, (const void**) &keys, (const void**) &values, + WXSIZEOF( keys ), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) ); + wxCFRef attrtext( CFAttributedStringCreate(kCFAllocatorDefault, t, attributes) ); + wxCFRef line( CTLineCreateWithAttributedString(attrtext) ); + + int chars = text.length(); + for ( int pos = 0; pos < (int)chars; pos ++ ) + { + widths[pos] = CTLineGetOffsetForStringIndex( line, pos+1 , NULL )+0.5; + } + + return; + } #endif - - ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle()); - ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 , - &chars , &style , &atsuLayout ); - - for ( int pos = 0; pos < (int)chars; pos ++ ) +#if wxMAC_USE_ATSU_TEXT { - unsigned long actualNumberOfBounds = 0; - ATSTrapezoid glyphBounds; - - // We get a single bound, since the text should only require one. If it requires more, there is an issue - OSStatus result; - result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1, - kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ); - if (result != noErr || actualNumberOfBounds != 1 ) - return; - - widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ); - //unsigned char uch = s[i]; + ATSUTextLayout atsuLayout; + wxMacUniCharBuffer unibuf( text ); + UniCharCount chars = unibuf.GetChars(); + + ATSUStyle style = (((wxMacCoreGraphicsFontData*)m_font.GetRefData())->GetATSUStyle()); + ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 , + &chars , &style , &atsuLayout ); + + for ( int pos = 0; pos < (int)chars; pos ++ ) + { + unsigned long actualNumberOfBounds = 0; + ATSTrapezoid glyphBounds; + + // We get a single bound, since the text should only require one. If it requires more, there is an issue + OSStatus result; + result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1, + kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds ); + if (result != noErr || actualNumberOfBounds != 1 ) + return; + + widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ); + //unsigned char uch = s[i]; + } + + ::ATSUDisposeTextLayout(atsuLayout); } - - ::ATSUDisposeTextLayout(atsuLayout); -#if SIZEOF_WCHAR_T == 4 - free( ubuf ) ; +#endif +#if wxMAC_USE_CG_TEXT + // TODO core graphics text implementation here #endif } @@ -1995,6 +2118,7 @@ public : // Context virtual wxGraphicsContext * CreateContext( const wxWindowDC& dc); + virtual wxGraphicsContext * CreateContext( const wxMemoryDC& dc); virtual wxGraphicsContext * CreateContextFromNativeContext( void * context ); @@ -2047,18 +2171,26 @@ wxGraphicsRenderer* wxGraphicsRenderer::GetDefaultRenderer() return &gs_MacCoreGraphicsRenderer; } -wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc) +wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxWindowDC& dc ) { - wxMemoryDC* mdc = wxDynamicCast(&dc, wxMemoryDC); - if ( mdc ) - { - return new wxMacCoreGraphicsContext(this, - (CGContextRef)mdc->GetGraphicsContext()->GetNativeContext()); - } - else - { - return new wxMacCoreGraphicsContext(this,(CGContextRef)dc.GetWindow()->MacGetCGContextRef() ); - } + const wxDCImpl* impl = dc.GetImpl(); + wxWindowDCImpl *win_impl = wxDynamicCast( impl, wxWindowDCImpl ); + if (win_impl) + return new wxMacCoreGraphicsContext( this, + (CGContextRef)(win_impl->GetWindow()->MacGetCGContextRef()) ); + + return NULL; +} + +wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContext( const wxMemoryDC& dc ) +{ + const wxDCImpl* impl = dc.GetImpl(); + wxMemoryDCImpl *mem_impl = wxDynamicCast( impl, wxMemoryDCImpl ); + if (mem_impl) + return new wxMacCoreGraphicsContext( this, + (CGContextRef)(mem_impl->GetGraphicsContext()->GetNativeContext()) ); + + return NULL; } wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateContextFromNativeContext( void * context ) @@ -2164,3 +2296,67 @@ wxGraphicsFont wxMacCoreGraphicsRenderer::CreateFont( const wxFont &font , const return wxNullGraphicsFont; } +// +// CoreGraphics Helper Methods +// + +// Data Providers and Consumers + +size_t UMAPutBytesCFRefCallback( void *info, const void *bytes, size_t count ) +{ + CFMutableDataRef data = (CFMutableDataRef) info; + if ( data ) + { + CFDataAppendBytes( data, (const UInt8*) bytes, count ); + } + return count; +} + +void wxMacReleaseCFDataProviderCallback(void *info, + const void *WXUNUSED(data), + size_t WXUNUSED(count)) +{ + if ( info ) + CFRelease( (CFDataRef) info ); +} + +void wxMacReleaseCFDataConsumerCallback( void *info ) +{ + if ( info ) + CFRelease( (CFDataRef) info ); +} + +CGDataProviderRef wxMacCGDataProviderCreateWithCFData( CFDataRef data ) +{ + if ( data == NULL ) + return NULL; + + return CGDataProviderCreateWithCFData( data ); +} + +CGDataConsumerRef wxMacCGDataConsumerCreateWithCFData( CFMutableDataRef data ) +{ + if ( data == NULL ) + return NULL; + + return CGDataConsumerCreateWithCFData( data ); +} + +void wxMacReleaseMemoryBufferProviderCallback(void *info, const void *data, size_t WXUNUSED(size)) +{ + wxMemoryBuffer* membuf = (wxMemoryBuffer*) info ; + + wxASSERT( data == membuf->GetData() ) ; + + delete membuf ; +} + +CGDataProviderRef wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffer& buf ) +{ + wxMemoryBuffer* b = new wxMemoryBuffer( buf ); + if ( b->GetDataLen() == 0 ) + return NULL; + + return CGDataProviderCreateWithData( b , (const void *) b->GetData() , b->GetDataLen() , + wxMacReleaseMemoryBufferProviderCallback ); +} \ No newline at end of file