📄 dccg.cpp
字号:
blit = wxNullBitmap ;
}
}
else
{
blit = wxNullBitmap ;
}
}
if ( blit.Ok() )
{
CGContextRef cg = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
CGImageRef image = (CGImageRef)( blit.CGImageCreate() ) ;
HIRect r = CGRectMake( xxdest , yydest , wwdest , hhdest ) ;
HIViewDrawCGImage( cg , &r , image ) ;
CGImageRelease( image ) ;
}
}
else
{
#if 0
CGContextRef cg = (wxMacCGContext*)(source->GetGraphicContext())->GetNativeContext() ;
void *data = CGBitmapContextGetData( cg ) ;
#endif
return false ; // wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") ) ;
}
return true;
}
void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
double angle)
{
wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRotatedText - invalid DC") );
wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoDrawRotatedText - no valid font set") );
if ( str.length() == 0 )
return ;
if ( m_logicalFunction != wxCOPY )
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
#endif
int drawX = XLOG2DEVMAC(x) ;
int drawY = YLOG2DEVMAC(y) ;
status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
&chars , (ATSUStyle*) &m_macATSUIStyle , &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 );
if ( abs(iAngle) > 0 )
{
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 ) ;
}
{
CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
ATSUAttributeTag atsuTags[] =
{
kATSUCGContextTag ,
} ;
ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
{
sizeof( CGContextRef ) ,
} ;
ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
{
&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 ;
if ( m_backgroundMode == wxSOLID )
{
wxGraphicPath* 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 ;
}
drawX += (int)(sin(angle / RAD2DEG) * FixedToInt(ascent));
drawY += (int)(cos(angle / RAD2DEG) * FixedToInt(ascent));
status = ::ATSUMeasureTextImage( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
IntToFixed(drawX) , IntToFixed(drawY) , &rect );
wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
CGContextSaveGState(((wxMacCGContext*)(m_graphicContext))->GetNativeContext());
CGContextTranslateCTM(((wxMacCGContext*)(m_graphicContext))->GetNativeContext(), drawX, drawY);
CGContextScaleCTM(((wxMacCGContext*)(m_graphicContext))->GetNativeContext(), 1, -1);
status = ::ATSUDrawText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
IntToFixed(0) , IntToFixed(0) );
wxASSERT_MSG( status == noErr , wxT("couldn't draw the rotated text") );
CGContextRestoreGState( ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ) ;
CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) );
CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) );
::ATSUDisposeTextLayout(atsuLayout);
#if SIZEOF_WCHAR_T == 4
free( ubuf ) ;
#endif
}
void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
{
wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawText - invalid DC") );
DoDrawRotatedText( strtext , x , y , 0.0 ) ;
}
bool wxDC::CanGetTextExtent() const
{
wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::CanGetTextExtent - invalid DC") );
return true ;
}
void wxDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height,
wxCoord *descent, wxCoord *externalLeading ,
wxFont *theFont ) const
{
wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoGetTextExtent - invalid DC") );
wxFont formerFont = m_font ;
if ( theFont )
{
// work around the const-ness
*((wxFont*)(&m_font)) = *theFont ;
MacInstallFont() ;
}
if ( str.empty() )
return ;
wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoGetTextExtent - no valid font set") ) ;
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
#endif
status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
&chars , (ATSUStyle*) &m_macATSUIStyle , &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 = YDEV2LOGREL( FixedToInt(textAscent + textDescent) ) ;
if ( descent )
*descent =YDEV2LOGREL( FixedToInt(textDescent) );
if ( externalLeading )
*externalLeading = 0 ;
if ( width )
*width = XDEV2LOGREL( FixedToInt(textAfter - textBefore) ) ;
::ATSUDisposeTextLayout(atsuLayout);
#if SIZEOF_WCHAR_T == 4
free( ubuf ) ;
#endif
if ( theFont )
{
// work around the constness
*((wxFont*)(&m_font)) = formerFont ;
MacInstallFont() ;
}
}
bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
{
wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoGetPartialTextExtents - invalid DC") );
widths.Empty();
widths.Add(0, text.length());
if (text.empty())
return false;
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
#endif
OSStatus status;
status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
&chars , (ATSUStyle*) &m_macATSUIStyle , &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 false;
widths[pos] = XDEV2LOGREL(FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ));
//unsigned char uch = s[i];
}
::ATSUDisposeTextLayout(atsuLayout);
return true;
}
wxCoord wxDC::GetCharWidth(void) const
{
wxCoord width ;
DoGetTextExtent( wxT("g") , &width , NULL , NULL , NULL , NULL ) ;
return width ;
}
wxCoord wxDC::GetCharHeight(void) const
{
wxCoord height ;
DoGetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL ) ;
return height ;
}
void wxDC::Clear(void)
{
wxCHECK_RET( Ok(), wxT("wxDC(cg)::Clear - invalid DC") );
if (m_backgroundBrush.Ok() && m_backgroundBrush.GetStyle() != wxTRANSPARENT)
{
HIRect rect = CGRectMake( -10000 , -10000 , 20000 , 20000 ) ;
CGContextRef cg = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
switch ( m_backgroundBrush.MacGetBrushKind() )
{
case kwxMacBrushTheme :
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
if ( HIThemeSetFill != 0 )
{
HIThemeSetFill( m_backgroundBrush.MacGetTheme(), NULL, cg, kHIThemeOrientationNormal );
CGContextFillRect(cg, rect);
}
else
#endif
{
RGBColor color;
GetThemeBrushAsColor( m_backgroundBrush.MacGetTheme(), 32, true, &color );
CGContextSetRGBFillColor( cg, (float) color.red / 65536,
(float) color.green / 65536, (float) color.blue / 65536, 1 );
CGContextFillRect( cg, rect );
}
// reset to normal value
RGBColor col = MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
CGContextSetRGBFillColor( cg, col.red / 65536.0, col.green / 65536.0, col.blue / 65536.0, 1.0 );
}
break ;
case kwxMacBrushThemeBackground :
{
wxFAIL_MSG( wxT("There shouldn't be theme backgrounds under Quartz") ) ;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
if ( UMAGetSystemVersion() >= 0x1030 )
{
HIThemeBackgroundDrawInfo drawInfo ;
drawInfo.version = 0 ;
drawInfo.state = kThemeStateActive ;
drawInfo.kind = m_backgroundBrush.MacGetThemeBackground( NULL ) ;
if ( drawInfo.kind == kThemeBackgroundMetal )
{
HIThemeDrawBackground( &rect, &drawInfo, cg, kHIThemeOrientationNormal ) ;
HIThemeApplyBackground( &rect, &drawInfo, cg, kHIThemeOrientationNormal ) ;
}
}
#endif
}
break ;
case kwxMacBrushColour :
{
// FIXME: doesn't correctly render stippled brushes !!
// FIXME: should this be replaced by ::SetBrush() ??
RGBColor col = MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel()) ;
CGContextSetRGBFillColor( cg , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
CGContextFillRect(cg, rect);
// reset to normal value
col = MAC_WXCOLORREF( GetBrush().GetColour().GetPixel() ) ;
CGContextSetRGBFillColor( cg , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
}
break ;
default :
wxFAIL_MSG( wxT("unknown brush kind") ) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -