further encapsulation of graphics context, wxdc becoming 'generic'
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41370 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -152,6 +152,10 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
|
|||||||
// state we were called with, the other one after changing to HI Graphics orientation
|
// state we were called with, the other one after changing to HI Graphics orientation
|
||||||
// (this one is used for getting back clippings etc)
|
// (this one is used for getting back clippings etc)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// wxGraphicPath implementation
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxMacCGPath::wxMacCGPath()
|
wxMacCGPath::wxMacCGPath()
|
||||||
{
|
{
|
||||||
m_path = CGPathCreateMutable() ;
|
m_path = CGPathCreateMutable() ;
|
||||||
@@ -200,16 +204,34 @@ CGPathRef wxMacCGPath::GetPath() const
|
|||||||
return m_path ;
|
return m_path ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxMacCGPath::AddArcToPoint( wxCoord x1, wxCoord y1 , wxCoord x2, wxCoord y2, wxCoord r )
|
||||||
|
{
|
||||||
|
CGPathAddArcToPoint( m_path, NULL , x1, y1, x2, y2, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGPath::AddArc( wxCoord x, wxCoord y, wxCoord r, double startAngle, double endAngle, bool clockwise )
|
||||||
|
{
|
||||||
|
CGPathAddArc( m_path, NULL , x, y, r, startAngle, endAngle, clockwise);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// wxGraphicContext implementation
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxMacCGContext::wxMacCGContext( CGrafPtr port )
|
wxMacCGContext::wxMacCGContext( CGrafPtr port )
|
||||||
{
|
{
|
||||||
m_qdPort = port ;
|
m_qdPort = port ;
|
||||||
m_cgContext = NULL ;
|
m_cgContext = NULL ;
|
||||||
|
m_mode = kCGPathFill;
|
||||||
|
m_macATSUIStyle = NULL ;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMacCGContext::wxMacCGContext( CGContextRef cgcontext )
|
wxMacCGContext::wxMacCGContext( CGContextRef cgcontext )
|
||||||
{
|
{
|
||||||
m_qdPort = NULL ;
|
m_qdPort = NULL ;
|
||||||
m_cgContext = cgcontext ;
|
m_cgContext = cgcontext ;
|
||||||
|
m_mode = kCGPathFill;
|
||||||
|
m_macATSUIStyle = NULL ;
|
||||||
CGContextSaveGState( m_cgContext ) ;
|
CGContextSaveGState( m_cgContext ) ;
|
||||||
CGContextSaveGState( m_cgContext ) ;
|
CGContextSaveGState( m_cgContext ) ;
|
||||||
}
|
}
|
||||||
@@ -218,6 +240,8 @@ wxMacCGContext::wxMacCGContext()
|
|||||||
{
|
{
|
||||||
m_qdPort = NULL ;
|
m_qdPort = NULL ;
|
||||||
m_cgContext = NULL ;
|
m_cgContext = NULL ;
|
||||||
|
m_mode = kCGPathFill;
|
||||||
|
m_macATSUIStyle = NULL ;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMacCGContext::~wxMacCGContext()
|
wxMacCGContext::~wxMacCGContext()
|
||||||
@@ -327,6 +351,50 @@ void wxMacCGContext::SetNativeContext( CGContextRef cg )
|
|||||||
m_cgContext = cg ;
|
m_cgContext = cg ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::Translate( wxCoord dx , wxCoord dy )
|
||||||
|
{
|
||||||
|
CGContextTranslateCTM( m_cgContext, dx, dy );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::Scale( wxCoord xScale , wxCoord yScale )
|
||||||
|
{
|
||||||
|
CGContextScaleCTM( m_cgContext , xScale , yScale ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::DrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, wxCoord w, wxCoord h )
|
||||||
|
{
|
||||||
|
CGImageRef image = (CGImageRef)( bmp.CGImageCreate() ) ;
|
||||||
|
HIRect r = CGRectMake( x , y , w , h ) ;
|
||||||
|
HIViewDrawCGImage( m_cgContext , &r , image ) ;
|
||||||
|
CGImageRelease( image ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::DrawIcon( const wxIcon &icon, wxCoord x, wxCoord y, wxCoord w, wxCoord h )
|
||||||
|
{
|
||||||
|
CGRect r = CGRectMake( 00 , 00 , w , h ) ;
|
||||||
|
CGContextSaveGState( m_cgContext );
|
||||||
|
CGContextTranslateCTM( m_cgContext, x , y + h );
|
||||||
|
CGContextScaleCTM( m_cgContext, 1, -1 );
|
||||||
|
PlotIconRefInContext( m_cgContext , &r , kAlignNone , kTransformNone ,
|
||||||
|
NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) ) ;
|
||||||
|
CGContextRestoreGState( m_cgContext ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::PushState()
|
||||||
|
{
|
||||||
|
CGContextSaveGState( m_cgContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::PopState()
|
||||||
|
{
|
||||||
|
CGContextRestoreGState( m_cgContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::SetTextColor( const wxColour &col )
|
||||||
|
{
|
||||||
|
m_textForegroundColor = col ;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark wxMacCGPattern, ImagePattern, HatchPattern classes
|
#pragma mark wxMacCGPattern, ImagePattern, HatchPattern classes
|
||||||
|
|
||||||
@@ -769,43 +837,294 @@ void wxMacCGContext::SetBrush( const wxBrush &brush )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddEllipticArcToPath(CGContextRef c, CGPoint center, CGFloat a, CGFloat b, CGFloat fromDegree , CGFloat toDegree )
|
void wxMacCGContext::DrawText( const wxString &str, wxCoord x, wxCoord y, double angle )
|
||||||
{
|
{
|
||||||
CGContextSaveGState(c);
|
OSStatus status = noErr ;
|
||||||
CGContextTranslateCTM(c, center.x, center.y);
|
ATSUTextLayout atsuLayout ;
|
||||||
CGContextScaleCTM(c, a, b);
|
UniCharCount chars = str.length() ;
|
||||||
CGContextMoveToPoint(c, 1, 0);
|
UniChar* ubuf = NULL ;
|
||||||
CGContextAddArc(c, 0, 0, 1, DegToRad(fromDegree), DegToRad(toDegree), 0);
|
|
||||||
CGContextClosePath(c);
|
|
||||||
CGContextRestoreGState(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddRoundedRectToPath(CGContextRef c, CGRect rect, CGFloat ovalWidth,
|
#if SIZEOF_WCHAR_T == 4
|
||||||
CGFloat ovalHeight)
|
wxMBConvUTF16 converter ;
|
||||||
{
|
#if wxUSE_UNICODE
|
||||||
CGFloat fw, fh;
|
size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ;
|
||||||
if (ovalWidth == 0 || ovalHeight == 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 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 )
|
||||||
{
|
{
|
||||||
CGContextAddRect(c, rect);
|
Fixed atsuAngle = IntToFixed( iAngle ) ;
|
||||||
return;
|
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 ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextSaveGState(c);
|
{
|
||||||
CGContextTranslateCTM(c, CGRectGetMinX(rect), CGRectGetMinY(rect));
|
ATSUAttributeTag atsuTags[] =
|
||||||
CGContextScaleCTM(c, ovalWidth, ovalHeight);
|
{
|
||||||
|
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 ) ;
|
||||||
|
}
|
||||||
|
|
||||||
fw = CGRectGetWidth(rect) / ovalWidth;
|
ATSUTextMeasurement textBefore, textAfter ;
|
||||||
fh = CGRectGetHeight(rect) / ovalHeight;
|
ATSUTextMeasurement ascent, descent ;
|
||||||
|
|
||||||
CGContextMoveToPoint(c, fw, fh / 2);
|
status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
|
||||||
CGContextAddArcToPoint(c, fw, fh, fw / 2, fh, 1);
|
&textBefore , &textAfter, &ascent , &descent );
|
||||||
CGContextAddArcToPoint(c, 0, fh, 0, fh / 2, 1);
|
|
||||||
CGContextAddArcToPoint(c, 0, 0, fw / 2, 0, 1);
|
wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
|
||||||
CGContextAddArcToPoint(c, fw, 0, fw, fh / 2, 1);
|
|
||||||
CGContextClosePath(c);
|
Rect rect ;
|
||||||
CGContextRestoreGState(c);
|
/*
|
||||||
|
// TODO
|
||||||
|
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 ;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
x += (int)(sin(angle / RAD2DEG) * FixedToInt(ascent));
|
||||||
|
y += (int)(cos(angle / RAD2DEG) * 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::GetTextExtent( const wxString &str, wxCoord *width, wxCoord *height,
|
||||||
|
wxCoord *descent, wxCoord *externalLeading ) const
|
||||||
|
{
|
||||||
|
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 = FixedToInt(textAscent + textDescent) ;
|
||||||
|
if ( descent )
|
||||||
|
*descent = FixedToInt(textDescent) ;
|
||||||
|
if ( externalLeading )
|
||||||
|
*externalLeading = 0 ;
|
||||||
|
if ( width )
|
||||||
|
*width = FixedToInt(textAfter - textBefore) ;
|
||||||
|
|
||||||
|
::ATSUDisposeTextLayout(atsuLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::GetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
|
||||||
|
{
|
||||||
|
widths.Empty();
|
||||||
|
widths.Add(0, text.length());
|
||||||
|
|
||||||
|
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
|
||||||
|
#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 ;
|
||||||
|
|
||||||
|
widths[pos] = FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
|
||||||
|
//unsigned char uch = s[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
::ATSUDisposeTextLayout(atsuLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxMacCGContext::SetFont( const wxFont &font )
|
||||||
|
{
|
||||||
|
if ( m_macATSUIStyle )
|
||||||
|
{
|
||||||
|
::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
|
||||||
|
m_macATSUIStyle = NULL ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( font.Ok() )
|
||||||
|
{
|
||||||
|
OSStatus status ;
|
||||||
|
|
||||||
|
status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , (ATSUStyle*) &m_macATSUIStyle ) ;
|
||||||
|
|
||||||
|
wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") ) ;
|
||||||
|
|
||||||
|
// we need the scale here ...
|
||||||
|
|
||||||
|
Fixed atsuSize = IntToFixed( int( /*m_scaleY*/ 1 * font.MacGetFontSize()) ) ;
|
||||||
|
RGBColor atsuColor = MAC_WXCOLORREF( m_textForegroundColor.GetPixel() ) ;
|
||||||
|
ATSUAttributeTag atsuTags[] =
|
||||||
|
{
|
||||||
|
kATSUSizeTag ,
|
||||||
|
kATSUColorTag ,
|
||||||
|
} ;
|
||||||
|
ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
|
||||||
|
{
|
||||||
|
sizeof( Fixed ) ,
|
||||||
|
sizeof( RGBColor ) ,
|
||||||
|
} ;
|
||||||
|
ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
|
||||||
|
{
|
||||||
|
&atsuSize ,
|
||||||
|
&atsuColor ,
|
||||||
|
} ;
|
||||||
|
|
||||||
|
status = ::ATSUSetAttributes(
|
||||||
|
(ATSUStyle)m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
|
||||||
|
atsuTags, atsuSizes, atsuValues);
|
||||||
|
|
||||||
|
wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
wxDC::wxDC()
|
wxDC::wxDC()
|
||||||
@@ -861,11 +1180,7 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask
|
|||||||
wxCoord ww = XLOG2DEVREL(w);
|
wxCoord ww = XLOG2DEVREL(w);
|
||||||
wxCoord hh = YLOG2DEVREL(h);
|
wxCoord hh = YLOG2DEVREL(h);
|
||||||
|
|
||||||
CGContextRef cg = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
|
m_graphicContext->DrawBitmap( bmp, xx , yy , ww , hh ) ;
|
||||||
CGImageRef image = (CGImageRef)( bmp.CGImageCreate() ) ;
|
|
||||||
HIRect r = CGRectMake( xx , yy , ww , hh ) ;
|
|
||||||
HIViewDrawCGImage( cg , &r , image ) ;
|
|
||||||
CGImageRelease( image ) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
|
void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
|
||||||
@@ -880,14 +1195,7 @@ void wxDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
|
|||||||
wxCoord ww = XLOG2DEVREL(w);
|
wxCoord ww = XLOG2DEVREL(w);
|
||||||
wxCoord hh = YLOG2DEVREL(h);
|
wxCoord hh = YLOG2DEVREL(h);
|
||||||
|
|
||||||
CGContextRef cg = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
|
m_graphicContext->DrawIcon( icon , xx, yy, ww, hh ) ;
|
||||||
CGRect r = CGRectMake( 00 , 00 , ww , hh ) ;
|
|
||||||
CGContextSaveGState( cg );
|
|
||||||
CGContextTranslateCTM( cg, xx , yy + hh );
|
|
||||||
CGContextScaleCTM( cg, 1, -1 );
|
|
||||||
PlotIconRefInContext( cg , &r , kAlignNone , kTransformNone ,
|
|
||||||
NULL , kPlotIconRefNormalFlags , MAC_WXHICON( icon.GetHICON() ) ) ;
|
|
||||||
CGContextRestoreGState( cg ) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
|
void wxDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
|
||||||
@@ -1012,7 +1320,7 @@ void wxDC::SetTextForeground( const wxColour &col )
|
|||||||
if ( col != m_textForegroundColour )
|
if ( col != m_textForegroundColour )
|
||||||
{
|
{
|
||||||
m_textForegroundColour = col;
|
m_textForegroundColour = col;
|
||||||
MacInstallFont() ;
|
m_graphicContext->SetTextColor( col ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1137,7 +1445,8 @@ void wxDC::SetBackgroundMode( int mode )
|
|||||||
void wxDC::SetFont( const wxFont &font )
|
void wxDC::SetFont( const wxFont &font )
|
||||||
{
|
{
|
||||||
m_font = font;
|
m_font = font;
|
||||||
MacInstallFont() ;
|
if ( m_graphicContext )
|
||||||
|
m_graphicContext->SetFont( font ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::SetPen( const wxPen &pen )
|
void wxDC::SetPen( const wxPen &pen )
|
||||||
@@ -1156,12 +1465,11 @@ void wxDC::SetPen( const wxPen &pen )
|
|||||||
{
|
{
|
||||||
// we have to compensate for moved device origins etc. otherwise patterned pens are standing still
|
// we have to compensate for moved device origins etc. otherwise patterned pens are standing still
|
||||||
// eg when using a wxScrollWindow and scrolling around
|
// eg when using a wxScrollWindow and scrolling around
|
||||||
CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
|
|
||||||
int origX = XLOG2DEVMAC( 0 ) ;
|
int origX = XLOG2DEVMAC( 0 ) ;
|
||||||
int origY = YLOG2DEVMAC( 0 ) ;
|
int origY = YLOG2DEVMAC( 0 ) ;
|
||||||
CGContextTranslateCTM( cgContext, origX, origY );
|
m_graphicContext->Translate( origX , origY ) ;
|
||||||
m_graphicContext->SetPen( m_pen ) ;
|
m_graphicContext->SetPen( m_pen ) ;
|
||||||
CGContextTranslateCTM( cgContext, -origX, -origY );
|
m_graphicContext->Translate( -origX , -origY ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1182,12 +1490,11 @@ void wxDC::SetBrush( const wxBrush &brush )
|
|||||||
{
|
{
|
||||||
// we have to compensate for moved device origins etc. otherwise patterned brushes are standing still
|
// we have to compensate for moved device origins etc. otherwise patterned brushes are standing still
|
||||||
// eg when using a wxScrollWindow and scrolling around
|
// eg when using a wxScrollWindow and scrolling around
|
||||||
CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
|
|
||||||
int origX = XLOG2DEVMAC(0) ;
|
int origX = XLOG2DEVMAC(0) ;
|
||||||
int origY = YLOG2DEVMAC(0) ;
|
int origY = YLOG2DEVMAC(0) ;
|
||||||
CGContextTranslateCTM( cgContext, origX, origY );
|
m_graphicContext->Translate( origX , origY ) ;
|
||||||
m_graphicContext->SetBrush( m_brush ) ;
|
m_graphicContext->SetBrush( m_brush ) ;
|
||||||
CGContextTranslateCTM( cgContext, -origX, -origY );
|
m_graphicContext->Translate( -origX , -origY ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1339,18 +1646,19 @@ void wxDC::DoDrawArc( wxCoord x1, wxCoord y1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool fill = m_brush.GetStyle() != wxTRANSPARENT ;
|
bool fill = m_brush.GetStyle() != wxTRANSPARENT ;
|
||||||
wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
|
|
||||||
CGContextRef ctx = mctx->GetNativeContext() ;
|
wxGraphicPath* path = m_graphicContext->CreatePath() ;
|
||||||
CGContextSaveGState( ctx ) ;
|
m_graphicContext->PushState() ;
|
||||||
CGContextTranslateCTM( ctx, xxc , yyc );
|
m_graphicContext->Translate( xxc, yyc ) ;
|
||||||
CGContextScaleCTM( ctx , 1 , -1 ) ;
|
m_graphicContext->Scale( 1, -1 ) ;
|
||||||
if ( fill )
|
if ( fill )
|
||||||
CGContextMoveToPoint( ctx , 0 , 0 ) ;
|
path->MoveToPoint( 0, 0 ) ;
|
||||||
CGContextAddArc( ctx, 0, 0 , rad , DegToRad(sa), DegToRad(ea), 0 );
|
path->AddArc( 0, 0, rad , DegToRad(sa) , DegToRad(ea), false ) ;
|
||||||
if ( fill )
|
if ( fill )
|
||||||
CGContextAddLineToPoint( ctx , 0 , 0 ) ;
|
path->AddLineToPoint( 0, 0 ) ;
|
||||||
CGContextRestoreGState( ctx ) ;
|
m_graphicContext->DrawPath( path ) ;
|
||||||
CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
|
m_graphicContext->PopState() ;
|
||||||
|
delete path ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
|
void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
|
||||||
@@ -1380,19 +1688,18 @@ void wxDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
|
|||||||
|
|
||||||
bool fill = m_brush.GetStyle() != wxTRANSPARENT ;
|
bool fill = m_brush.GetStyle() != wxTRANSPARENT ;
|
||||||
|
|
||||||
wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
|
wxGraphicPath* path = m_graphicContext->CreatePath() ;
|
||||||
CGContextRef ctx = mctx->GetNativeContext() ;
|
m_graphicContext->PushState() ;
|
||||||
|
m_graphicContext->Translate( xx + ww / 2, yy + hh / 2 ) ;
|
||||||
CGContextSaveGState( ctx ) ;
|
m_graphicContext->Scale( 1 * ww / 2 , -1 * hh / 2 ) ;
|
||||||
CGContextTranslateCTM( ctx, xx + ww / 2, yy + hh / 2 );
|
|
||||||
CGContextScaleCTM( ctx , 1 * ww / 2 , -1 * hh / 2 ) ;
|
|
||||||
if ( fill )
|
if ( fill )
|
||||||
CGContextMoveToPoint( ctx , 0 , 0 ) ;
|
path->MoveToPoint( 0, 0 ) ;
|
||||||
CGContextAddArc( ctx, 0, 0, 1, DegToRad( sa ), DegToRad( ea ), 0 );
|
path->AddArc( 0, 0, 1 , DegToRad(sa) , DegToRad(ea), false ) ;
|
||||||
if ( fill )
|
if ( fill )
|
||||||
CGContextAddLineToPoint( ctx , 0 , 0 ) ;
|
path->AddLineToPoint( 0, 0 ) ;
|
||||||
CGContextRestoreGState( ctx ) ;
|
m_graphicContext->DrawPath( path ) ;
|
||||||
CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
|
m_graphicContext->PopState() ;
|
||||||
|
delete path ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::DoDrawPoint( wxCoord x, wxCoord y )
|
void wxDC::DoDrawPoint( wxCoord x, wxCoord y )
|
||||||
@@ -1589,10 +1896,29 @@ void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
|
|||||||
yy = yy - hh;
|
yy = yy - hh;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
|
wxGraphicPath* path = m_graphicContext->CreatePath() ;
|
||||||
CGContextRef ctx = mctx->GetNativeContext() ;
|
if ( radius == 0)
|
||||||
AddRoundedRectToPath( ctx , CGRectMake( xx , yy , ww , hh ) , radius , radius ) ;
|
{
|
||||||
CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
|
path->AddRectangle( xx , yy , ww , hh ) ;
|
||||||
|
m_graphicContext->DrawPath( path ) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_graphicContext->PushState() ;
|
||||||
|
m_graphicContext->Translate( xx , yy ) ;
|
||||||
|
m_graphicContext->Scale( radius , radius ) ;
|
||||||
|
double fw = ww / radius ;
|
||||||
|
double fh = hh / radius;
|
||||||
|
path->MoveToPoint(fw, fh / 2);
|
||||||
|
path->AddArcToPoint(fw, fh, fw / 2, fh, 1);
|
||||||
|
path->AddArcToPoint(0, fh, 0, fh / 2, 1);
|
||||||
|
path->AddArcToPoint(0, 0, fw / 2, 0, 1);
|
||||||
|
path->AddArcToPoint(fw, 0, fw, fh / 2, 1);
|
||||||
|
path->CloseSubpath();
|
||||||
|
m_graphicContext->DrawPath( path ) ;
|
||||||
|
m_graphicContext->PopState() ;
|
||||||
|
}
|
||||||
|
delete path ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
|
void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
|
||||||
@@ -1623,14 +1949,14 @@ void wxDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
|
|||||||
yy = yy - hh;
|
yy = yy - hh;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMacCGContext* mctx = ((wxMacCGContext*) m_graphicContext) ;
|
wxGraphicPath* path = m_graphicContext->CreatePath() ;
|
||||||
CGContextRef ctx = mctx->GetNativeContext() ;
|
m_graphicContext->PushState() ;
|
||||||
CGContextSaveGState( ctx ) ;
|
m_graphicContext->Translate(xx + ww / 2, yy + hh / 2);
|
||||||
CGContextTranslateCTM( ctx, xx + ww / 2, yy + hh / 2 );
|
m_graphicContext->Scale(ww / 2 , hh / 2);
|
||||||
CGContextScaleCTM( ctx , ww / 2 , hh / 2 ) ;
|
path->AddArc( 0, 0, 1, 0 , 2 * M_PI , false ) ;
|
||||||
CGContextAddArc( ctx, 0, 0, 1, 0 , 2 * M_PI , 0 );
|
m_graphicContext->DrawPath( path ) ;
|
||||||
CGContextRestoreGState( ctx ) ;
|
m_graphicContext->PopState() ;
|
||||||
CGContextDrawPath( ctx , mctx->GetDrawingMode() ) ;
|
delete path ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDC::CanDrawBitmap() const
|
bool wxDC::CanDrawBitmap() const
|
||||||
@@ -1684,6 +2010,7 @@ bool wxDC::DoBlit(
|
|||||||
if ( xxsrc >= 0 && yysrc >= 0 )
|
if ( xxsrc >= 0 && yysrc >= 0 )
|
||||||
{
|
{
|
||||||
wxRect subrect( xxsrc, yysrc, wwsrc , hhsrc ) ;
|
wxRect subrect( xxsrc, yysrc, wwsrc , hhsrc ) ;
|
||||||
|
// TODO we perhaps could add a DrawSubBitmap call to dc for performance reasons
|
||||||
blit = blit.GetSubBitmap( subrect ) ;
|
blit = blit.GetSubBitmap( subrect ) ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1701,21 +2028,13 @@ bool wxDC::DoBlit(
|
|||||||
|
|
||||||
if ( blit.Ok() )
|
if ( blit.Ok() )
|
||||||
{
|
{
|
||||||
CGContextRef cg = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
|
m_graphicContext->DrawBitmap( blit, xxdest , yydest , wwdest , hhdest ) ;
|
||||||
CGImageRef image = (CGImageRef)( blit.CGImageCreate() ) ;
|
|
||||||
HIRect r = CGRectMake( xxdest , yydest , wwdest , hhdest ) ;
|
|
||||||
HIViewDrawCGImage( cg , &r , image ) ;
|
|
||||||
CGImageRelease( image ) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if 0
|
wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") ) ;
|
||||||
CGContextRef cg = (wxMacCGContext*)(source->GetGraphicContext())->GetNativeContext() ;
|
return false ;
|
||||||
void *data = CGBitmapContextGetData( cg ) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false ; // wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") ) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1725,143 +2044,17 @@ void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
|
|||||||
double angle)
|
double angle)
|
||||||
{
|
{
|
||||||
wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRotatedText - invalid DC") );
|
wxCHECK_RET( Ok(), wxT("wxDC(cg)::DoDrawRotatedText - invalid DC") );
|
||||||
wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoDrawRotatedText - no valid font set") );
|
// wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoDrawRotatedText - no valid font set") );
|
||||||
|
|
||||||
if ( str.length() == 0 )
|
if ( str.length() == 0 )
|
||||||
return ;
|
return ;
|
||||||
if ( m_logicalFunction != wxCOPY )
|
if ( m_logicalFunction != wxCOPY )
|
||||||
return ;
|
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 drawX = XLOG2DEVMAC(x) ;
|
||||||
int drawY = YLOG2DEVMAC(y) ;
|
int drawY = YLOG2DEVMAC(y) ;
|
||||||
|
|
||||||
status = ::ATSUCreateTextLayoutWithTextPtr( (UniCharArrayPtr) ubuf , 0 , chars , chars , 1 ,
|
m_graphicContext->DrawText( str, drawX ,drawY , angle ) ;
|
||||||
&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)
|
void wxDC::DoDrawText(const wxString& strtext, wxCoord x, wxCoord y)
|
||||||
@@ -1887,75 +2080,25 @@ void wxDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height
|
|||||||
wxFont formerFont = m_font ;
|
wxFont formerFont = m_font ;
|
||||||
if ( theFont )
|
if ( theFont )
|
||||||
{
|
{
|
||||||
// work around the const-ness
|
m_graphicContext->SetFont( *theFont ) ;
|
||||||
*((wxFont*)(&m_font)) = *theFont ;
|
|
||||||
MacInstallFont() ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( str.empty() )
|
wxCoord h , d , e , w ;
|
||||||
return ;
|
|
||||||
|
|
||||||
wxCHECK_RET( m_macATSUIStyle != NULL, wxT("wxDC(cg)::DoGetTextExtent - no valid font set") ) ;
|
m_graphicContext->GetTextExtent( str, &w, &h, &d, &e ) ;
|
||||||
|
|
||||||
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 )
|
if ( height )
|
||||||
*height = YDEV2LOGREL( FixedToInt(textAscent + textDescent) ) ;
|
*height = YDEV2LOGREL( h ) ;
|
||||||
if ( descent )
|
if ( descent )
|
||||||
*descent =YDEV2LOGREL( FixedToInt(textDescent) );
|
*descent =YDEV2LOGREL( d);
|
||||||
if ( externalLeading )
|
if ( externalLeading )
|
||||||
*externalLeading = 0 ;
|
*externalLeading = YDEV2LOGREL( e);
|
||||||
if ( width )
|
if ( width )
|
||||||
*width = XDEV2LOGREL( FixedToInt(textAfter - textBefore) ) ;
|
*width = XDEV2LOGREL( w ) ;
|
||||||
|
|
||||||
::ATSUDisposeTextLayout(atsuLayout);
|
|
||||||
|
|
||||||
#if SIZEOF_WCHAR_T == 4
|
|
||||||
free( ubuf ) ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( theFont )
|
if ( theFont )
|
||||||
{
|
{
|
||||||
// work around the constness
|
m_graphicContext->SetFont( m_font ) ;
|
||||||
*((wxFont*)(&m_font)) = formerFont ;
|
|
||||||
MacInstallFont() ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1963,60 +2106,10 @@ bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) con
|
|||||||
{
|
{
|
||||||
wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoGetPartialTextExtents - invalid DC") );
|
wxCHECK_MSG( Ok(), false, wxT("wxDC(cg)::DoGetPartialTextExtents - invalid DC") );
|
||||||
|
|
||||||
widths.Empty();
|
m_graphicContext->GetPartialTextExtents( text, widths ) ;
|
||||||
widths.Add(0, text.length());
|
for ( size_t i = 0 ; i < widths.GetCount() ; ++i )
|
||||||
|
widths[i] = XDEV2LOGREL( widths[i] );
|
||||||
|
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2114,50 +2207,6 @@ void wxDC::Clear(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::MacInstallFont() const
|
|
||||||
{
|
|
||||||
wxCHECK_RET( Ok(), wxT("wxDC(cg)::MacInstallFont - invalid DC") );
|
|
||||||
|
|
||||||
if ( m_macATSUIStyle )
|
|
||||||
{
|
|
||||||
::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
|
|
||||||
m_macATSUIStyle = NULL ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( m_font.Ok() )
|
|
||||||
{
|
|
||||||
OSStatus status ;
|
|
||||||
|
|
||||||
status = ATSUCreateAndCopyStyle( (ATSUStyle) m_font.MacGetATSUStyle() , (ATSUStyle*) &m_macATSUIStyle ) ;
|
|
||||||
|
|
||||||
wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") ) ;
|
|
||||||
|
|
||||||
Fixed atsuSize = IntToFixed( int(m_scaleY * m_font.MacGetFontSize()) ) ;
|
|
||||||
RGBColor atsuColor = MAC_WXCOLORREF( m_textForegroundColour.GetPixel() ) ;
|
|
||||||
ATSUAttributeTag atsuTags[] =
|
|
||||||
{
|
|
||||||
kATSUSizeTag ,
|
|
||||||
kATSUColorTag ,
|
|
||||||
} ;
|
|
||||||
ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
|
|
||||||
{
|
|
||||||
sizeof( Fixed ) ,
|
|
||||||
sizeof( RGBColor ) ,
|
|
||||||
} ;
|
|
||||||
ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
|
|
||||||
{
|
|
||||||
&atsuSize ,
|
|
||||||
&atsuColor ,
|
|
||||||
} ;
|
|
||||||
|
|
||||||
status = ::ATSUSetAttributes(
|
|
||||||
(ATSUStyle)m_macATSUIStyle, sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
|
|
||||||
atsuTags, atsuSizes, atsuValues);
|
|
||||||
|
|
||||||
wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") ) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user