switching all text rendering/measuring to ATSUI

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39894 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Csomor
2006-06-29 17:25:40 +00:00
parent dfd468aafd
commit 757302fda3

View File

@@ -1474,7 +1474,6 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y, void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
double angle) double angle)
{ {
// TODO: support text background color (only possible by hand, ATSUI does not support it)
wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText - invalid DC") ); wxCHECK_RET( Ok(), wxT("wxDC::DoDrawRotatedText - invalid DC") );
if ( str.empty() ) if ( str.empty() )
@@ -1483,44 +1482,13 @@ void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
wxMacFastPortSetter helper(this) ; wxMacFastPortSetter helper(this) ;
MacInstallFont() ; MacInstallFont() ;
#if 0
if ( 0 )
{
m_macFormerAliasState = IsAntiAliasedTextEnabled(&m_macFormerAliasSize);
SetAntiAliasedTextEnabled(true, SInt16(m_scaleY * m_font.MacGetFontSize()));
m_macAliasWasEnabled = true ;
}
#endif
OSStatus status = noErr ; OSStatus status = noErr ;
ATSUTextLayout atsuLayout ; ATSUTextLayout atsuLayout ;
UniCharCount chars = str.length() ;
UniChar* ubuf = NULL ;
#if SIZEOF_WCHAR_T == 4 wxMacUniCharBuffer unibuf( str ) ;
wxMBConvUTF16 converter ; UniCharCount chars = unibuf.GetChars() ;
#if wxUSE_UNICODE
size_t unicharlen = converter.WC2MB( NULL , str.wc_str() , 0 ) ; status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 ,
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 ) ; &chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") ); wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the rotated text") );
@@ -1535,29 +1503,66 @@ void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
ATSUTextMeasurement textBefore, textAfter ; ATSUTextMeasurement textBefore, textAfter ;
ATSUTextMeasurement ascent, descent ; ATSUTextMeasurement ascent, descent ;
if ( abs(iAngle) > 0 ) ATSLineLayoutOptions layoutOptions = kATSLineNoLayoutOptions ;
if (m_font.GetNoAntiAliasing())
{ {
Fixed atsuAngle = IntToFixed( iAngle ) ; layoutOptions |= kATSLineNoAntiAliasing ;
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 ) ;
} }
Fixed atsuAngle = IntToFixed( iAngle ) ;
ATSUAttributeTag atsuTags[] =
{
kATSULineLayoutOptionsTag ,
kATSULineRotationTag ,
} ;
ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
{
sizeof( ATSLineLayoutOptions ) ,
sizeof( Fixed ) ,
} ;
ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
{
&layoutOptions ,
&atsuAngle ,
} ;
status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags)/sizeof(ATSUAttributeTag) - ( abs(iAngle) > 0.001 ? 0 : 1),
atsuTags, atsuSizes, atsuValues ) ;
status = ::ATSUMeasureText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd, status = ::ATSUMeasureText( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
&textBefore , &textAfter, &ascent , &descent ); &textBefore , &textAfter, &ascent , &descent );
wxASSERT_MSG( status == noErr , wxT("couldn't measure the rotated text") );
if ( m_backgroundMode == wxSOLID )
{
// background painting must be done by hand, cannot be done by ATSUI
wxCoord x2 , y2 ;
PolyHandle polygon = OpenPoly();
::MoveTo(drawX, drawY);
x2 = (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent)) ;
y2 = (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent)) ;
::LineTo(x2, y2);
x2 = (int) (drawX + sin(angle / RAD2DEG) * FixedToInt(ascent + descent ) + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ;
y2 = (int) (drawY + cos(angle / RAD2DEG) * FixedToInt(ascent + descent) - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ;
::LineTo(x2, y2);
x2 = (int) (drawX + cos(angle / RAD2DEG) * FixedToInt(textAfter)) ;
y2 = (int) (drawY - sin(angle / RAD2DEG) * FixedToInt(textAfter)) ;
::LineTo(x2, y2);
::LineTo( drawX, drawY) ;
ClosePoly();
::ErasePoly( polygon );
KillPoly( polygon );
}
drawX += (int)(sin(angle / RAD2DEG) * FixedToInt(ascent)); drawX += (int)(sin(angle / RAD2DEG) * FixedToInt(ascent));
drawY += (int)(cos(angle / RAD2DEG) * FixedToInt(ascent)); drawY += (int)(cos(angle / RAD2DEG) * FixedToInt(ascent));
@@ -1575,87 +1580,11 @@ void wxDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) ); CalcBoundingBox(XDEV2LOG(rect.left), YDEV2LOG(rect.top) );
CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) ); CalcBoundingBox(XDEV2LOG(rect.right), YDEV2LOG(rect.bottom) );
::ATSUDisposeTextLayout(atsuLayout); ::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)
{ {
wxCHECK_RET(Ok(), wxT("wxDC::DoDrawText - invalid DC")); DoDrawRotatedText( strtext , x , y , 0) ;
wxMacFastPortSetter helper(this) ;
long xx = XLOG2DEVMAC(x);
long yy = YLOG2DEVMAC(y);
#if TARGET_CARBON
bool useDrawThemeText = ( DrawThemeTextBox != (void*) kUnresolvedCFragSymbolAddress ) ;
if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || m_font.GetNoAntiAliasing() )
useDrawThemeText = false ;
#endif
MacInstallFont() ;
FontInfo fi ;
::GetFontInfo( &fi ) ;
#if TARGET_CARBON
if ( !useDrawThemeText )
yy += fi.ascent ;
#else
yy += fi.ascent ;
#endif
::TextMode( (m_backgroundMode == wxTRANSPARENT) ? srcOr : srcCopy ) ;
::MoveTo( xx , yy );
int line = 0 ;
{
wxString linetext = strtext ;
#if TARGET_CARBON
if ( useDrawThemeText )
{
Rect frame = {
yy + line*(fi.descent + fi.ascent + fi.leading), xx ,
yy + (line+1)*(fi.descent + fi.ascent + fi.leading) , xx + 10000 } ;
wxMacCFStringHolder mString( linetext , m_font.GetEncoding()) ;
if ( m_backgroundMode != wxTRANSPARENT )
{
Point bounds = {0, 0} ;
Rect background = frame ;
SInt16 baseline ;
::GetThemeTextDimensions( mString,
m_font.MacGetThemeFontID() ,
kThemeStateActive,
false,
&bounds,
&baseline );
background.right = background.left + bounds.h ;
background.bottom = background.top + bounds.v ;
::EraseRect( &background ) ;
}
::DrawThemeTextBox( mString,
m_font.MacGetThemeFontID() ,
kThemeStateActive,
false,
&frame,
teJustLeft,
NULL );
}
else
#endif
{
wxCharBuffer text = linetext.mb_str(wxConvLocal) ;
if ( text.data() != NULL )
::DrawText( text , 0 , strlen(text) ) ;
}
}
::TextMode( srcOr ) ;
} }
bool wxDC::CanGetTextExtent() const bool wxDC::CanGetTextExtent() const
@@ -1665,7 +1594,8 @@ bool wxDC::CanGetTextExtent() const
return true ; return true ;
} }
void wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *height,
void wxDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height,
wxCoord *descent, wxCoord *externalLeading , wxCoord *descent, wxCoord *externalLeading ,
wxFont *theFont ) const wxFont *theFont ) const
{ {
@@ -1680,54 +1610,63 @@ void wxDC::DoGetTextExtent( const wxString &strtext, wxCoord *width, wxCoord *he
} }
MacInstallFont() ; MacInstallFont() ;
FontInfo fi ;
::GetFontInfo( &fi ) ;
#if TARGET_CARBON OSStatus status = noErr ;
bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ; ATSUTextLayout atsuLayout ;
if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || ((wxFont*)&m_font)->GetNoAntiAliasing() )
useGetThemeText = false ; wxMacUniCharBuffer unibuf( str ) ;
#endif UniCharCount chars = unibuf.GetChars() ;
status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 ,
&chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
status = ::ATSUSetTransientFontMatching( atsuLayout , true ) ;
wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
ATSLineLayoutOptions layoutOptions = kATSLineNoLayoutOptions ;
if (m_font.GetNoAntiAliasing())
{
layoutOptions |= kATSLineNoAntiAliasing ;
}
ATSUAttributeTag atsuTags[] =
{
kATSULineLayoutOptionsTag ,
} ;
ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
{
sizeof( ATSLineLayoutOptions ) ,
} ;
ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
{
&layoutOptions ,
} ;
status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags)/sizeof(ATSUAttributeTag) ,
atsuTags, atsuSizes, atsuValues ) ;
ATSUTextMeasurement textBefore, textAfter ;
ATSUTextMeasurement textAscent, textDescent ;
status = ::ATSUGetUnjustifiedBounds( atsuLayout, kATSUFromTextBeginning, kATSUToTextEnd,
&textBefore , &textAfter, &textAscent , &textDescent );
if ( height ) if ( height )
*height = YDEV2LOGREL( fi.descent + fi.ascent ) ; *height = YDEV2LOGREL( FixedToInt(textAscent + textDescent) ) ;
if ( descent ) if ( descent )
*descent =YDEV2LOGREL( fi.descent ); *descent =YDEV2LOGREL( FixedToInt(textDescent) );
if ( externalLeading ) if ( externalLeading )
*externalLeading = YDEV2LOGREL( fi.leading ) ; *externalLeading = 0 ;
int curwidth = 0 ;
if ( width ) if ( width )
{ *width = XDEV2LOGREL( FixedToInt(textAfter - textBefore) ) ;
*width = 0 ;
wxString linetext = strtext ;
if ( useGetThemeText ) ::ATSUDisposeTextLayout(atsuLayout);
{
Point bounds = {0, 0} ;
SInt16 baseline ;
wxMacCFStringHolder mString( linetext , m_font.GetEncoding() ) ;
ThemeFontID themeFont = m_font.MacGetThemeFontID() ;
::GetThemeTextDimensions( mString,
themeFont ,
kThemeStateActive,
false,
&bounds,
&baseline );
curwidth = bounds.h ;
}
else
{
wxCharBuffer text = linetext.mb_str(wxConvLocal) ;
if ( text.data() != NULL )
curwidth = ::TextWidth( text , 0 , strlen(text) ) ;
else
curwidth = 0 ;
}
if ( curwidth > *width )
*width = XDEV2LOGREL( curwidth ) ;
}
if ( theFont ) if ( theFont )
{ {
@@ -1750,110 +1689,77 @@ bool wxDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) con
wxMacFastPortSetter helper(this) ; wxMacFastPortSetter helper(this) ;
MacInstallFont() ; MacInstallFont() ;
#if TARGET_CARBON OSStatus status = noErr ;
bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ; ATSUTextLayout atsuLayout ;
if ( UMAGetSystemVersion() < 0x1000 || IsKindOf(CLASSINFO( wxPrinterDC ) ) || ((wxFont*)&m_font)->GetNoAntiAliasing() )
useGetThemeText = false ; wxMacUniCharBuffer unibuf( text ) ;
UniCharCount chars = unibuf.GetChars() ;
status = ::ATSUCreateTextLayoutWithTextPtr( unibuf.GetBuffer() , 0 , chars , chars , 1 ,
&chars , (ATSUStyle*) &m_macATSUIStyle , &atsuLayout ) ;
if ( useGetThemeText ) wxASSERT_MSG( status == noErr , wxT("couldn't create the layout of the text") );
status = ::ATSUSetTransientFontMatching( atsuLayout , true ) ;
wxASSERT_MSG( status == noErr , wxT("couldn't setup transient font matching") );
ATSLineLayoutOptions layoutOptions = kATSLineNoLayoutOptions ;
if (m_font.GetNoAntiAliasing())
{ {
// If anybody knows how to do this more efficiently yet still handle layoutOptions |= kATSLineNoAntiAliasing ;
// the fractional glyph widths that may be present when using AA
// fonts, please change it. Currently it is measuring from the
// beginning of the string for each succeeding substring, which is much
// slower than this should be.
for (size_t i=0; i<text.length(); i++)
{
wxString str(text.Left(i + 1));
Point bounds = {0, 0};
SInt16 baseline ;
wxMacCFStringHolder mString(str, m_font.GetEncoding());
::GetThemeTextDimensions( mString,
m_font.MacGetThemeFontID(),
kThemeStateActive,
false,
&bounds,
&baseline );
widths[i] = XDEV2LOGREL(bounds.h);
}
} }
else
#endif ATSUAttributeTag atsuTags[] =
{ {
wxCharBuffer buff = text.mb_str(wxConvLocal); kATSULineLayoutOptionsTag ,
if ( buff.data() == 0 ) } ;
{
for (size_t i=0; i<text.length(); i++) ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
widths[i] = 0 ; {
} sizeof( ATSLineLayoutOptions ) ,
else } ;
{
size_t len = strlen(buff); ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
short* measurements = new short[len+1]; {
MeasureText(len, buff.data(), measurements); &layoutOptions ,
} ;
status = ::ATSUSetLayoutControls(atsuLayout , sizeof(atsuTags)/sizeof(ATSUAttributeTag) ,
atsuTags, atsuSizes, atsuValues ) ;
for ( int pos = 0; pos < (int)chars ; pos ++ )
{
unsigned long actualNumberOfBounds = 0;
ATSTrapezoid glyphBounds;
// Copy to widths, starting at measurements[1] // We get a single bound, since the text should only require one. If it requires more, there is an issue
// NOTE: this doesn't take into account any multi-byte characters OSStatus result;
// in buff, it probably should... result = ATSUGetGlyphBounds( atsuLayout, 0, 0, kATSUFromTextBeginning, pos + 1,
for (size_t i=0; i<text.length(); i++) kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
widths[i] = XDEV2LOGREL(measurements[i + 1]); if (result != noErr || actualNumberOfBounds != 1 )
return false;
delete [] measurements; widths[pos] = XDEV2LOGREL(FixedToInt( glyphBounds.upperRight.x - glyphBounds.upperLeft.x ));
}
} }
::ATSUDisposeTextLayout(atsuLayout);
return true; return true;
} }
wxCoord wxDC::GetCharWidth(void) const wxCoord wxDC::GetCharWidth(void) const
{ {
wxCHECK_MSG(Ok(), 1, wxT("wxDC::GetCharWidth - invalid DC")); wxCoord width = 0 ;
DoGetTextExtent( wxT("g"), &width , NULL , NULL , NULL , NULL ) ;
wxMacFastPortSetter helper(this) ; return width ;
int width = 0 ;
const char text[] = "g" ;
MacInstallFont() ;
#if TARGET_CARBON
bool useGetThemeText = ( GetThemeTextDimensions != (void*) kUnresolvedCFragSymbolAddress ) ;
if ( UMAGetSystemVersion() < 0x1000 || ((wxFont*)&m_font)->GetNoAntiAliasing() )
useGetThemeText = false ;
if ( useGetThemeText )
{
Point bounds = {0, 0} ;
SInt16 baseline ;
CFStringRef mString = CFStringCreateWithBytes( NULL , (UInt8*) text , 1 , CFStringGetSystemEncoding(), false ) ;
::GetThemeTextDimensions( mString,
m_font.MacGetThemeFontID(),
kThemeStateActive,
false,
&bounds,
&baseline );
CFRelease( mString ) ;
width = bounds.h ;
}
else
#endif
{
width = ::TextWidth( text , 0 , 1 ) ;
}
return YDEV2LOGREL(width) ;
} }
wxCoord wxDC::GetCharHeight(void) const wxCoord wxDC::GetCharHeight(void) const
{ {
wxCHECK_MSG(Ok(), 1, wxT("wxDC::GetCharHeight - invalid DC")); wxCoord height ;
DoGetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL ) ;
wxMacFastPortSetter helper(this) ; return height ;
MacInstallFont() ;
FontInfo fi ;
::GetFontInfo( &fi ) ;
return YDEV2LOGREL( fi.descent + fi.ascent );
} }
void wxDC::Clear(void) void wxDC::Clear(void)