📄 dccg.cpp
字号:
public : wxMacCGPattern() {} // is guaranteed to be called only with a non-Null CGContextRef virtual void Render( CGContextRef ctxRef ) = 0 ; operator CGPatternRef() const { return m_patternRef ; }protected : virtual ~wxMacCGPattern() { // as this is called only when the m_patternRef is been released; // don't release it again } static void _Render( void *info, CGContextRef ctxRef ) { wxMacCGPattern* self = (wxMacCGPattern*) info ; if ( self && ctxRef ) self->Render( ctxRef ) ; } static void _Dispose( void *info ) { wxMacCGPattern* self = (wxMacCGPattern*) info ; delete self ; } CGPatternRef m_patternRef ; static const CGPatternCallbacks ms_Callbacks ;} ;const CGPatternCallbacks wxMacCGPattern::ms_Callbacks = { 0, &wxMacCGPattern::_Render, &wxMacCGPattern::_Dispose };class ImagePattern : public wxMacCGPattern{public : ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform ) { wxASSERT( bmp && bmp->Ok() ) ; Init( (CGImageRef) bmp->CGImageCreate() , transform ) ; } // ImagePattern takes ownership of CGImageRef passed in ImagePattern( CGImageRef image , const CGAffineTransform& transform ) { if ( image ) CFRetain( image ) ; Init( image , transform ) ; } virtual void Render( CGContextRef ctxRef ) { if (m_image != NULL) HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image ); }protected : void Init( CGImageRef image, const CGAffineTransform& transform ) { m_image = image ; if ( m_image ) { m_imageBounds = CGRectMake( 0.0, 0.0, (CGFloat)CGImageGetWidth( m_image ), (CGFloat)CGImageGetHeight( m_image ) ) ; m_patternRef = CGPatternCreate( this , m_imageBounds, transform , m_imageBounds.size.width, m_imageBounds.size.height, kCGPatternTilingNoDistortion, true , &wxMacCGPattern::ms_Callbacks ) ; } } virtual ~ImagePattern() { if ( m_image ) CGImageRelease( m_image ) ; } CGImageRef m_image ; CGRect m_imageBounds ;} ;class HatchPattern : public wxMacCGPattern{public : HatchPattern( int hatchstyle, const CGAffineTransform& transform ) { m_hatch = hatchstyle ; m_imageBounds = CGRectMake( 0.0, 0.0, 8.0 , 8.0 ) ; m_patternRef = CGPatternCreate( this , m_imageBounds, transform , m_imageBounds.size.width, m_imageBounds.size.height, kCGPatternTilingNoDistortion, false , &wxMacCGPattern::ms_Callbacks ) ; } 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); } } virtual void Render( CGContextRef ctxRef ) { switch ( m_hatch ) { case wxBDIAGONAL_HATCH : { CGPoint pts[] = { { 8.0 , 0.0 } , { 0.0 , 8.0 } }; StrokeLineSegments( ctxRef , pts , 2 ) ; } break ; case wxCROSSDIAG_HATCH : { CGPoint pts[] = { { 0.0 , 0.0 } , { 8.0 , 8.0 } , { 8.0 , 0.0 } , { 0.0 , 8.0 } }; StrokeLineSegments( ctxRef , pts , 4 ) ; } break ; case wxFDIAGONAL_HATCH : { CGPoint pts[] = { { 0.0 , 0.0 } , { 8.0 , 8.0 } }; StrokeLineSegments( ctxRef , pts , 2 ) ; } break ; case wxCROSS_HATCH : { CGPoint pts[] = { { 0.0 , 4.0 } , { 8.0 , 4.0 } , { 4.0 , 0.0 } , { 4.0 , 8.0 } , }; StrokeLineSegments( ctxRef , pts , 4 ) ; } break ; case wxHORIZONTAL_HATCH : { CGPoint pts[] = { { 0.0 , 4.0 } , { 8.0 , 4.0 } , }; StrokeLineSegments( ctxRef , pts , 2 ) ; } break ; case wxVERTICAL_HATCH : { CGPoint pts[] = { { 4.0 , 0.0 } , { 4.0 , 8.0 } , }; StrokeLineSegments( ctxRef , pts , 2 ) ; } break ; default: break; } }protected : virtual ~HatchPattern() {} CGRect m_imageBounds ; int m_hatch ;};#pragma mark -void wxMacCGContext::SetPen( const wxPen &pen ){ m_pen = pen ; if ( m_cgContext == NULL ) return ; bool fill = m_brush.GetStyle() != wxTRANSPARENT ; bool stroke = pen.GetStyle() != wxTRANSPARENT ;#if 0 // we can benchmark performance; should go into a setting eventually CGContextSetShouldAntialias( m_cgContext , false ) ;#endif if ( fill || stroke ) { // set up brushes m_mode = kCGPathFill ; // just a default if ( stroke ) { CGContextSetRGBStrokeColor( m_cgContext , pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 , pen.GetColour().Blue() / 255.0 , pen.GetColour().Alpha() / 255.0 ) ; // TODO: * m_dc->m_scaleX CGFloat penWidth = pen.GetWidth(); if (penWidth <= 0.0) penWidth = 0.1; CGContextSetLineWidth( m_cgContext , penWidth ) ; CGLineCap cap ; switch ( pen.GetCap() ) { case wxCAP_ROUND : cap = kCGLineCapRound ; break ; case wxCAP_PROJECTING : cap = kCGLineCapSquare ; break ; case wxCAP_BUTT : cap = kCGLineCapButt ; break ; default : cap = kCGLineCapButt ; break ; } CGLineJoin join ; switch ( pen.GetJoin() ) { case wxJOIN_BEVEL : join = kCGLineJoinBevel ; break ; case wxJOIN_MITER : join = kCGLineJoinMiter ; break ; case wxJOIN_ROUND : join = kCGLineJoinRound ; break ; default : join = kCGLineJoinMiter ; break; } m_mode = kCGPathStroke ; int count = 0 ; const CGFloat *lengths = NULL ; CGFloat *userLengths = NULL ; const CGFloat dashUnit = penWidth < 1.0 ? 1.0 : penWidth; const CGFloat dotted[] = { dashUnit , dashUnit + 2.0 }; const CGFloat short_dashed[] = { 9.0 , 6.0 }; const CGFloat dashed[] = { 19.0 , 9.0 }; const CGFloat dotted_dashed[] = { 9.0 , 6.0 , 3.0 , 3.0 }; switch ( pen.GetStyle() ) { case wxSOLID : break ; case wxDOT : lengths = dotted ; count = WXSIZEOF(dotted); break ; case wxLONG_DASH : lengths = dashed ; count = WXSIZEOF(dashed) ; break ; case wxSHORT_DASH : lengths = short_dashed ; count = WXSIZEOF(short_dashed) ; break ; case wxDOT_DASH : lengths = dotted_dashed ; count = WXSIZEOF(dotted_dashed); break ; case wxUSER_DASH : wxDash *dashes ; count = pen.GetDashes( &dashes ) ; if ((dashes != NULL) && (count > 0)) { userLengths = new CGFloat[count] ; for ( int i = 0 ; i < count ; ++i ) { userLengths[i] = dashes[i] * dashUnit ; if ( i % 2 == 1 && userLengths[i] < dashUnit + 2.0 ) userLengths[i] = dashUnit + 2.0 ; else if ( i % 2 == 0 && userLengths[i] < dashUnit ) userLengths[i] = dashUnit ; } } lengths = userLengths ; break ; case wxSTIPPLE : { CGFloat alphaArray[1] = { 1.0 } ; wxBitmap* bmp = pen.GetStipple() ; if ( bmp && bmp->Ok() ) { wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) ) ; CGContextSetStrokeColorSpace( m_cgContext , patternSpace ) ; wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) ); CGContextSetStrokePattern( m_cgContext, pattern , alphaArray ) ; } } break ; default : { wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ; CGContextSetStrokeColorSpace( m_cgContext , patternSpace ) ; wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( pen.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) ); CGFloat colorArray[4] = { pen.GetColour().Red() / 255.0 , pen.GetColour().Green() / 255.0 , pen.GetColour().Blue() / 255.0 , pen.GetColour().Alpha() / 255.0 } ; CGContextSetStrokePattern( m_cgContext, pattern , colorArray ) ; } break ; } if ((lengths != NULL) && (count > 0)) { CGContextSetLineDash( m_cgContext , 0 , lengths , count ) ; // force the line cap, otherwise we get artifacts (overlaps) and just solid lines cap = kCGLineCapButt ; } else { CGContextSetLineDash( m_cgContext , 0 , NULL , 0 ) ; } CGContextSetLineCap( m_cgContext , cap ) ; CGContextSetLineJoin( m_cgContext , join ) ; delete[] userLengths ; } if ( fill && stroke ) m_mode = kCGPathFillStroke ; }}void wxMacCGContext::SetBrush( const wxBrush &brush ){ m_brush = brush ; if ( m_cgContext == NULL ) return ; bool fill = brush.GetStyle() != wxTRANSPARENT ; bool stroke = m_pen.GetStyle() != wxTRANSPARENT ;#if 0 // we can benchmark performance, should go into a setting later CGContextSetShouldAntialias( m_cgContext , false ) ;#endif if ( fill || stroke ) { // setup brushes m_mode = kCGPathFill ; // just a default if ( fill ) { if ( brush.GetStyle() == wxSOLID ) { CGContextSetRGBFillColor( m_cgContext , brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 , brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 ) ; } else if ( brush.IsHatch() ) { wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ; CGContextSetFillColorSpace( m_cgContext , patternSpace ) ; wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( brush.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) ); CGFloat colorArray[4] = { brush.GetColour().Red() / 255.0 , brush.GetColour().Green() / 255.0 , brush.GetColour().Blue() / 255.0 , brush.GetColour().Alpha() / 255.0 } ; CGContextSetFillPattern( m_cgContext, pattern , colorArray ) ; } else { // now brush is a bitmap CGFloat alphaArray[1] = { 1.0 } ; wxBitmap* bmp = brush.GetStipple() ; if ( bmp && bmp->Ok() ) { wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) ) ; CGContextSetFillColorSpace( m_cgContext , patternSpace ) ; wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) ); CGContextSetFillPattern( m_cgContext, pattern , alphaArray ) ; } } m_mode = kCGPathFill ; } if ( fill && stroke ) m_mode = kCGPathFillStroke ; else if ( stroke ) m_mode = kCGPathStroke ; }}void wxMacCGContext::DrawText( const wxString &str, wxCoord x, wxCoord y, double angle ){ 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 ) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -