📄 dccg.cpp
字号:
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 :
~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 )
{
RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
CGContextSetRGBStrokeColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
// TODO: * m_dc->m_scaleX
float 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 float *lengths = NULL ;
float *userLengths = NULL ;
const float dashUnit = penWidth < 1.0 ? 1.0 : penWidth;
const float dotted[] = { dashUnit , dashUnit + 2.0 };
const float short_dashed[] = { 9.0 , 6.0 };
const float dashed[] = { 19.0 , 9.0 };
const float 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 float[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 :
{
float 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 ) ) ) );
RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
float colorArray[4] = { col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.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 )
{
RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
}
else if ( brush.IsHatch() )
{
wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
CGContextSetFillColorSpace( m_cgContext , patternSpace ) ;
wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( brush.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
float colorArray[4] = { col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 } ;
CGContextSetFillPattern( m_cgContext, pattern , colorArray ) ;
}
else
{
// now brush is a bitmap
float 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 AddEllipticArcToPath(CGContextRef c, CGPoint center, float a, float b, float fromDegree , float toDegree )
{
CGContextSaveGState(c);
CGContextTranslateCTM(c, center.x, center.y);
CGContextScaleCTM(c, a, b);
CGContextMoveToPoint(c, 1, 0);
CGContextAddArc(c, 0, 0, 1, DegToRad(fromDegree), DegToRad(toDegree), 0);
CGContextClosePath(c);
CGContextRestoreGState(c);
}
void AddRoundedRectToPath(CGContextRef c, CGRect rect, float ovalWidth,
float ovalHeight)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0)
{
CGContextAddRect(c, rect);
return;
}
CGContextSaveGState(c);
CGContextTranslateCTM(c, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM(c, ovalWidth, ovalHeight);
fw = CGRectGetWidth(rect) / ovalWidth;
fh = CGRectGetHeight(rect) / ovalHeight;
CGContextMoveToPoint(c, fw, fh / 2);
CGContextAddArcToPoint(c, fw, fh, fw / 2, fh, 1);
CGContextAddArcToPoint(c, 0, fh, 0, fh / 2, 1);
CGContextAddArcToPoint(c, 0, 0, fw / 2, 0, 1);
CGContextAddArcToPoint(c, fw, 0, fw, fh / 2, 1);
CGContextClosePath(c);
CGContextRestoreGState(c);
}
#pragma mark -
wxDC::wxDC()
{
m_ok = false ;
m_colour = true;
m_mm_to_pix_x = mm2pt;
m_mm_to_pix_y = mm2pt;
m_externalDeviceOriginX = 0;
m_externalDeviceOriginY = 0;
m_logicalScaleX = 1.0;
m_logicalScaleY = 1.0;
m_userScaleX = 1.0;
m_userScaleY = 1.0;
m_scaleX = 1.0;
m_scaleY = 1.0;
m_needComputeScaleX =
m_needComputeScaleY = false;
m_macPort = 0 ;
m_macLocalOrigin.x =
m_macLocalOrigin.y = 0 ;
m_pen = *wxBLACK_PEN;
m_font = *wxNORMAL_FONT;
m_brush = *wxWHITE_BRUSH;
m_macATSUIStyle = NULL ;
m_graphicContext = NULL ;
}
wxDC::~wxDC()
{
if ( m_macATSUIStyle )
{
::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
m_macATSUIStyle = NULL ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -