📄 dc.cpp
字号:
&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;
// 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 ));
}
::ATSUDisposeTextLayout(atsuLayout);
return true;
}
wxCoord wxDC::GetCharWidth(void) const
{
wxCoord width = 0 ;
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::Clear - invalid DC"));
wxMacFastPortSetter helper(this) ;
Rect rect = { -31000 , -31000 , 31000 , 31000 } ;
if ( m_backgroundBrush.Ok() && m_backgroundBrush.GetStyle() != wxTRANSPARENT)
{
::PenNormal() ;
MacSetupBackgroundForCurrentPort( m_backgroundBrush ) ;
::EraseRect( &rect ) ;
}
}
void wxDC::MacInstallFont() const
{
wxCHECK_RET(Ok(), wxT("Invalid DC"));
// if ( m_macFontInstalled )
// return ;
Pattern blackColor ;
MacSetupBackgroundForCurrentPort(m_backgroundBrush) ;
if ( m_backgroundMode != wxTRANSPARENT )
{
Pattern whiteColor ;
::BackPat(GetQDGlobalsWhite(&whiteColor));
}
wxASSERT( m_font.Ok() ) ;
::TextFont( m_font.MacGetFontNum() ) ;
::TextSize( (short)(m_scaleY * m_font.MacGetFontSize()) ) ;
::TextFace( m_font.MacGetFontStyle() ) ;
m_macFontInstalled = true ;
m_macBrushInstalled = false ;
m_macPenInstalled = false ;
RGBColor forecolor = MAC_WXCOLORREF( m_textForegroundColour.GetPixel());
RGBColor backcolor = MAC_WXCOLORREF( m_textBackgroundColour.GetPixel());
::RGBForeColor( &forecolor );
::RGBBackColor( &backcolor );
// TODO:
short mode = patCopy ;
switch ( m_logicalFunction )
{
case wxCOPY: // src
mode = patCopy ;
break ;
case wxINVERT: // NOT dst
::PenPat(GetQDGlobalsBlack(&blackColor));
mode = patXor ;
break ;
case wxXOR: // src XOR dst
mode = patXor ;
break ;
case wxOR_REVERSE: // src OR (NOT dst)
mode = notPatOr ;
break ;
case wxSRC_INVERT: // (NOT src)
mode = notPatCopy ;
break ;
case wxAND: // src AND dst
mode = adMin ;
break ;
// TODO: unsupported
case wxCLEAR: // 0
case wxAND_REVERSE:// src AND (NOT dst)
case wxAND_INVERT: // (NOT src) AND dst
case wxNO_OP: // dst
case wxNOR: // (NOT src) AND (NOT dst)
case wxEQUIV: // (NOT src) XOR dst
case wxOR_INVERT: // (NOT src) OR dst
case wxNAND: // (NOT src) OR (NOT dst)
case wxOR: // src OR dst
case wxSET: // 1
// case wxSRC_OR: // source _bitmap_ OR destination
// case wxSRC_AND: // source _bitmap_ AND destination
break ;
default:
break ;
}
::PenMode( mode ) ;
OSStatus status = noErr ;
status = ATSUCreateAndCopyStyle( (ATSUStyle) m_font.MacGetATSUStyle() , (ATSUStyle*) &m_macATSUIStyle ) ;
wxASSERT_MSG( status == noErr , wxT("couldn't set create ATSU style") ) ;
Fixed atsuSize = IntToFixed( int(m_scaleY * m_font.MacGetFontSize()) ) ;
ATSUAttributeTag atsuTags[] =
{
kATSUSizeTag ,
} ;
ByteCount atsuSizes[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
{
sizeof( Fixed ) ,
} ;
ATSUAttributeValuePtr atsuValues[sizeof(atsuTags)/sizeof(ATSUAttributeTag)] =
{
&atsuSize ,
} ;
status = ::ATSUSetAttributes((ATSUStyle)m_macATSUIStyle, sizeof(atsuTags)/sizeof(ATSUAttributeTag) ,
atsuTags, atsuSizes, atsuValues);
wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") ) ;
}
Pattern gPatterns[] =
{
// hatch patterns
{ { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } } ,
{ { 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 } } ,
{ { 0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } } ,
{ { 0x10 , 0x10 , 0x10 , 0xFF , 0x10 , 0x10 , 0x10 , 0x10 } } ,
{ { 0x00 , 0x00 , 0x00 , 0xFF , 0x00 , 0x00 , 0x00 , 0x00 } } ,
{ { 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 , 0x10 } } ,
{ { 0x81 , 0x42 , 0x24 , 0x18 , 0x18 , 0x24 , 0x42 , 0x81 } } ,
// dash patterns
{ { 0xCC , 0x99 , 0x33 , 0x66 , 0xCC , 0x99 , 0x33 , 0x66 } } , // DOT
{ { 0xFE , 0xFD , 0xFB , 0xF7 , 0xEF , 0xDF , 0xBF , 0x7F } } , // LONG_DASH
{ { 0xEE , 0xDD , 0xBB , 0x77 , 0xEE , 0xDD , 0xBB , 0x77 } } , // SHORT_DASH
{ { 0xDE , 0xBD , 0x7B , 0xF6 , 0xED , 0xDB , 0xB7 , 0x6F } } , // DOT_DASH
} ;
static void wxMacGetPattern(int penStyle, Pattern *pattern)
{
int index = 0; // solid pattern by default
switch (penStyle)
{
// hatches
case wxBDIAGONAL_HATCH: index = 1; break;
case wxFDIAGONAL_HATCH: index = 2; break;
case wxCROSS_HATCH: index = 3; break;
case wxHORIZONTAL_HATCH: index = 4; break;
case wxVERTICAL_HATCH: index = 5; break;
case wxCROSSDIAG_HATCH: index = 6; break;
// dashes
case wxDOT: index = 7; break;
case wxLONG_DASH: index = 8; break;
case wxSHORT_DASH: index = 9; break;
case wxDOT_DASH: index = 10; break;
default:
break;
}
*pattern = gPatterns[index];
}
void wxDC::MacInstallPen() const
{
wxCHECK_RET(Ok(), wxT("wxDC::MacInstallPen - invalid DC"));
//Pattern blackColor;
// if ( m_macPenInstalled )
// return ;
RGBColor forecolor = MAC_WXCOLORREF( m_pen.GetColour().GetPixel());
RGBColor backcolor = MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel());
::RGBForeColor( &forecolor );
::RGBBackColor( &backcolor );
::PenNormal() ;
// null means only one pixel, at whatever resolution
int penWidth = (int) (m_pen.GetWidth() * m_scaleX) ;
if ( penWidth == 0 )
penWidth = 1 ;
::PenSize(penWidth, penWidth);
Pattern pat;
int penStyle = m_pen.GetStyle();
if (penStyle == wxUSER_DASH)
{
// FIXME: there should be exactly 8 items in the dash
wxDash* dash ;
int number = m_pen.GetDashes(&dash) ;
int index = 0;
for ( int i = 0 ; i < 8 ; ++i )
{
pat.pat[i] = dash[index] ;
if (index < number - 1)
index++;
}
}
else
{
wxMacGetPattern(penStyle, &pat);
}
::PenPat(&pat);
// TODO:
short mode = patCopy ;
switch ( m_logicalFunction )
{
case wxCOPY: // only foreground color, leave background (thus not patCopy)
mode = patOr ;
break ;
case wxINVERT: // NOT dst
// ::PenPat(GetQDGlobalsBlack(&blackColor));
mode = patXor ;
break ;
case wxXOR: // src XOR dst
mode = patXor ;
break ;
case wxOR_REVERSE: // src OR (NOT dst)
mode = notPatOr ;
break ;
case wxSRC_INVERT: // (NOT src)
mode = notPatCopy ;
break ;
case wxAND: // src AND dst
mode = adMin ;
break ;
// TODO: unsupported
case wxCLEAR: // 0
case wxAND_REVERSE:// src AND (NOT dst)
case wxAND_INVERT: // (NOT src) AND dst
case wxNO_OP: // dst
case wxNOR: // (NOT src) AND (NOT dst)
case wxEQUIV: // (NOT src) XOR dst
case wxOR_INVERT: // (NOT src) OR dst
case wxNAND: // (NOT src) OR (NOT dst)
case wxOR: // src OR dst
case wxSET: // 1
// case wxSRC_OR: // source _bitmap_ OR destination
// case wxSRC_AND: // source _bitmap_ AND destination
break ;
default:
break ;
}
::PenMode( mode ) ;
m_macPenInstalled = true ;
m_macBrushInstalled = false ;
m_macFontInstalled = false ;
}
void wxDC::MacSetupBackgroundForCurrentPort(const wxBrush& background )
{
Pattern whiteColor ;
if ( background.Ok() )
{
switch ( background.MacGetBrushKind() )
{
case kwxMacBrushTheme :
::SetThemeBackground( background.MacGetTheme() , wxDisplayDepth() , true ) ;
break ;
case kwxMacBrushThemeBackground :
{
Rect extent ;
ThemeBackgroundKind bg = background.MacGetThemeBackground( &extent ) ;
::ApplyThemeBackground( bg , &extent, kThemeStateActive , wxDisplayDepth() , true ) ;
}
break ;
case kwxMacBrushColour :
{
::RGBBackColor( &MAC_WXCOLORREF( background.GetColour().GetPixel()) );
int brushStyle = background.GetStyle();
if (brushStyle == wxSOLID)
::BackPat(GetQDGlobalsWhite(&whiteColor));
else if (background.IsHatch())
{
Pattern pat ;
wxMacGetPattern(brushStyle, &pat);
::BackPat(&pat);
}
else
{
::BackPat(GetQDGlobalsWhite(&whiteColor));
}
}
break ;
default:
break ;
}
}
}
void wxDC::MacInstallBrush() const
{
wxCHECK_RET(Ok(), wxT("Invalid DC"));
// if ( m_macBrushInstalled )
// return ;
Pattern blackColor ;
bool backgroundTransparent = (GetBackgroundMode() == wxTRANSPARENT) ;
::RGBForeColor( &MAC_WXCOLORREF( m_brush.GetColour().GetPixel()) );
::RGBBackColor( &MAC_WXCOLORREF( m_backgroundBrush.GetColour().GetPixel()) );
int brushStyle = m_brush.GetStyle();
if (brushStyle == wxSOLID)
{
switch ( m_brush.MacGetBrushKind() )
{
case kwxMacBrushTheme :
{
Pattern whiteColor ;
::BackPat(GetQDGlobalsWhite(&whiteColor));
::SetThemePen( m_brush.MacGetTheme() , wxDisplayDepth() , true ) ;
}
break ;
default :
::PenPat(GetQDGlobalsBlack(&blackColor));
break ;
}
}
else if (m_brush.IsHatch())
{
Pattern pat ;
wxMacGetPattern(brushStyle, &pat);
::PenPat(&pat);
}
else if ( m_brush.GetStyle() == wxSTIPPLE || m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
{
// we force this in order to be compliant with wxMSW
backgroundTransparent = false ;
// for these the text fore (and back for MASK_OPAQUE) colors are used
wxBitmap* bitmap = m_brush.GetStipple() ;
int width = bitmap->GetWidth() ;
int height = bitmap->GetHeight() ;
GWorldPtr gw = NULL ;
if ( m_brush.GetStyle() == wxSTIPPLE )
gw = MAC_WXHBITMAP(bitmap->GetHBITMAP(NULL)) ;
else
gw = MAC_WXHBITMAP(bitmap->GetMask()->GetHBITMAP()) ;
PixMapHandle gwpixmaphandle = GetGWorldPixMap( gw ) ;
LockPixels( gwpixmaphandle ) ;
bool isMonochrome = !IsPortColor( gw ) ;
if ( !isMonochrome )
{
if ( (**gwpixmaphandle).pixelSize == 1 )
isMonochrome = true ;
}
if ( isMonochrome && width == 8 && height == 8 )
{
::RGBForeColor( &MAC_WXCOLORREF( m_textForegroundColour.GetPixel()) );
::RGBForeColor( &MAC_WXCOLORREF( m_textBackgroundColour.GetPixel()) );
BitMap* gwbitmap = (BitMap*) *gwpixmaphandle ; // since the color depth is 1 it is a BitMap
UInt8 *gwbits = (UInt8*) gwbitmap->baseAddr ;
int alignment = gwbitmap->rowBytes & 0x7FFF ;
Pattern pat ;
for ( int i = 0 ; i < 8 ; ++i )
{
pat.pat[i] = gwbits[i * alignment + 0] ;
}
UnlockPixels( GetGWorldPixMap( gw ) ) ;
::PenPat( &pat ) ;
}
else
{
// this will be the code to handle power of 2 patterns, we will have to arrive at a nice
// caching scheme before putting this into production
Handle image;
long imageSize;
PixPatHandle pixpat = NewPixPat() ;
CopyPixMap(gwpixmaphandle, (**pixpat).patMap);
imageSize = GetPixRowBytes((**pixpat).patMap) *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -