📄 dc.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dc.cpp
// Purpose: wxDC class
// Author: Stefan Csomor
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id: dc.cpp,v 1.132 2006/07/03 19:02:28 ABX Exp $
// Copyright: (c) Stefan Csomor
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/wxprec.h"
#include "wx/dc.h"
#if !wxMAC_USE_CORE_GRAPHICS
#ifndef WX_PRECOMP
#include "wx/log.h"
#include "wx/app.h"
#include "wx/dcmemory.h"
#include "wx/dcprint.h"
#include "wx/region.h"
#include "wx/image.h"
#endif
#include "wx/mac/uma.h"
#ifdef __MSL__
#if __MSL__ >= 0x6000
namespace std {}
using namespace std ;
#endif
#endif
#include "wx/mac/private.h"
#ifndef __DARWIN__
#include <ATSUnicode.h>
#include <TextCommon.h>
#include <TextEncodingConverter.h>
#endif
// set to 0 if problems arise
#define wxMAC_EXPERIMENTAL_DC 1
IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
const double RAD2DEG = 180.0 / M_PI;
const short kEmulatedMode = -1 ;
const short kUnsupportedMode = -2 ;
extern TECObjectRef s_TECNativeCToUnicode ;
wxMacPortSetter::wxMacPortSetter( const wxDC* dc ) :
m_ph( (GrafPtr) dc->m_macPort )
{
wxASSERT( dc->Ok() ) ;
m_dc = dc ;
dc->MacSetupPort(&m_ph) ;
}
wxMacPortSetter::~wxMacPortSetter()
{
m_dc->MacCleanupPort(&m_ph) ;
}
#if wxMAC_EXPERIMENTAL_DC
class wxMacFastPortSetter
{
public :
wxMacFastPortSetter( const wxDC *dc )
{
wxASSERT( dc->Ok() ) ;
m_swapped = QDSwapPort( (GrafPtr) dc->m_macPort , &m_oldPort ) ;
m_clipRgn = NewRgn() ;
GetClip( m_clipRgn ) ;
m_dc = dc ;
dc->MacSetupPort( NULL ) ;
}
~wxMacFastPortSetter()
{
// SetPort( (GrafPtr) m_dc->m_macPort ) ;
SetClip( m_clipRgn ) ;
if ( m_swapped )
SetPort( m_oldPort ) ;
m_dc->MacCleanupPort( NULL ) ;
DisposeRgn( m_clipRgn ) ;
}
private :
bool m_swapped ;
RgnHandle m_clipRgn ;
GrafPtr m_oldPort ;
const wxDC* m_dc ;
} ;
#else
typedef wxMacPortSetter wxMacFastPortSetter ;
#endif
wxMacWindowClipper::wxMacWindowClipper( const wxWindow* win ) :
wxMacPortSaver( (GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) )
{
m_newPort =(GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
m_formerClip = NewRgn() ;
m_newClip = NewRgn() ;
GetClip( m_formerClip ) ;
if ( win )
{
// guard against half constructed objects, this just leads to a empty clip
if ( win->GetPeer() )
{
int x = 0 , y = 0;
win->MacWindowToRootWindow( &x, &y ) ;
// get area including focus rect
CopyRgn( (RgnHandle) ((wxWindow*)win)->MacGetVisibleRegion(true).GetWXHRGN() , m_newClip ) ;
if ( !EmptyRgn( m_newClip ) )
OffsetRgn( m_newClip , x , y ) ;
}
SetClip( m_newClip ) ;
}
}
wxMacWindowClipper::~wxMacWindowClipper()
{
SetPort( m_newPort ) ;
SetClip( m_formerClip ) ;
DisposeRgn( m_newClip ) ;
DisposeRgn( m_formerClip ) ;
}
wxMacWindowStateSaver::wxMacWindowStateSaver( const wxWindow* win ) :
wxMacWindowClipper( win )
{
// the port is already set at this point
m_newPort = (GrafPtr) GetWindowPort((WindowRef) win->MacGetTopLevelWindowRef()) ;
GetThemeDrawingState( &m_themeDrawingState ) ;
}
wxMacWindowStateSaver::~wxMacWindowStateSaver()
{
SetPort( m_newPort ) ;
SetThemeDrawingState( m_themeDrawingState , true ) ;
}
//-----------------------------------------------------------------------------
// Local functions
//-----------------------------------------------------------------------------
static inline double dmin(double a, double b) { return a < b ? a : b; }
static inline double dmax(double a, double b) { return a > b ? a : b; }
static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
//-----------------------------------------------------------------------------
// wxDC
//-----------------------------------------------------------------------------
// this function emulates all wx colour manipulations, used to verify the implementation
// by setting the mode in the blitting functions to kEmulatedMode
void wxMacCalculateColour( int logical_func , const RGBColor &srcColor , RGBColor &dstColor ) ;
void wxMacCalculateColour( int logical_func , const RGBColor &srcColor , RGBColor &dstColor )
{
switch ( logical_func )
{
case wxAND: // src AND dst
dstColor.red = dstColor.red & srcColor.red ;
dstColor.green = dstColor.green & srcColor.green ;
dstColor.blue = dstColor.blue & srcColor.blue ;
break ;
case wxAND_INVERT: // (NOT src) AND dst
dstColor.red = dstColor.red & ~srcColor.red ;
dstColor.green = dstColor.green & ~srcColor.green ;
dstColor.blue = dstColor.blue & ~srcColor.blue ;
break ;
case wxAND_REVERSE:// src AND (NOT dst)
dstColor.red = ~dstColor.red & srcColor.red ;
dstColor.green = ~dstColor.green & srcColor.green ;
dstColor.blue = ~dstColor.blue & srcColor.blue ;
break ;
case wxCLEAR: // 0
dstColor.red = 0 ;
dstColor.green = 0 ;
dstColor.blue = 0 ;
break ;
case wxCOPY: // src
dstColor.red = srcColor.red ;
dstColor.green = srcColor.green ;
dstColor.blue = srcColor.blue ;
break ;
case wxEQUIV: // (NOT src) XOR dst
dstColor.red = dstColor.red ^ ~srcColor.red ;
dstColor.green = dstColor.green ^ ~srcColor.green ;
dstColor.blue = dstColor.blue ^ ~srcColor.blue ;
break ;
case wxINVERT: // NOT dst
dstColor.red = ~dstColor.red ;
dstColor.green = ~dstColor.green ;
dstColor.blue = ~dstColor.blue ;
break ;
case wxNAND: // (NOT src) OR (NOT dst)
dstColor.red = ~dstColor.red | ~srcColor.red ;
dstColor.green = ~dstColor.green | ~srcColor.green ;
dstColor.blue = ~dstColor.blue | ~srcColor.blue ;
break ;
case wxNOR: // (NOT src) AND (NOT dst)
dstColor.red = ~dstColor.red & ~srcColor.red ;
dstColor.green = ~dstColor.green & ~srcColor.green ;
dstColor.blue = ~dstColor.blue & ~srcColor.blue ;
break ;
case wxOR: // src OR dst
dstColor.red = dstColor.red | srcColor.red ;
dstColor.green = dstColor.green | srcColor.green ;
dstColor.blue = dstColor.blue | srcColor.blue ;
break ;
case wxOR_INVERT: // (NOT src) OR dst
dstColor.red = dstColor.red | ~srcColor.red ;
dstColor.green = dstColor.green | ~srcColor.green ;
dstColor.blue = dstColor.blue | ~srcColor.blue ;
break ;
case wxOR_REVERSE: // src OR (NOT dst)
dstColor.red = ~dstColor.red | srcColor.red ;
dstColor.green = ~dstColor.green | srcColor.green ;
dstColor.blue = ~dstColor.blue | srcColor.blue ;
break ;
case wxSET: // 1
dstColor.red = 0xFFFF ;
dstColor.green = 0xFFFF ;
dstColor.blue = 0xFFFF ;
break ;
case wxSRC_INVERT: // (NOT src)
dstColor.red = ~srcColor.red ;
dstColor.green = ~srcColor.green ;
dstColor.blue = ~srcColor.blue ;
break ;
case wxXOR: // src XOR dst
dstColor.red = dstColor.red ^ srcColor.red ;
dstColor.green = dstColor.green ^ srcColor.green ;
dstColor.blue = dstColor.blue ^ srcColor.blue ;
break ;
case wxNO_OP: // dst
default:
break ;
}
}
wxDC::wxDC()
{
m_ok = false;
m_colour = true;
m_mm_to_pix_x = mm2pt;
m_mm_to_pix_y = mm2pt;
m_internalDeviceOriginX = 0;
m_internalDeviceOriginY = 0;
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 = false;
m_needComputeScaleY = false;
m_macPort = NULL ;
m_macMask = NULL ;
m_macFontInstalled = false ;
m_macBrushInstalled = false ;
m_macPenInstalled = false ;
m_macLocalOrigin.x = m_macLocalOrigin.y = 0 ;
m_macBoundaryClipRgn = NewRgn() ;
m_macCurrentClipRgn = NewRgn() ;
SetRectRgn( (RgnHandle) m_macBoundaryClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
SetRectRgn( (RgnHandle) m_macCurrentClipRgn , -32000 , -32000 , 32000 , 32000 ) ;
m_pen = *wxBLACK_PEN;
m_font = *wxNORMAL_FONT;
m_brush = *wxWHITE_BRUSH;
#ifdef __WXDEBUG__
// needed to debug possible errors with two active drawing methods at the same time on
// the same DC
m_macCurrentPortStateHelper = NULL ;
#endif
m_macATSUIStyle = NULL ;
m_macAliasWasEnabled = false;
m_macForegroundPixMap = NULL ;
m_macBackgroundPixMap = NULL ;
}
wxDC::~wxDC(void)
{
DisposeRgn( (RgnHandle) m_macBoundaryClipRgn ) ;
DisposeRgn( (RgnHandle) m_macCurrentClipRgn ) ;
}
void wxDC::MacSetupPort(wxMacPortStateHelper* help) const
{
#ifdef __WXDEBUG__
wxASSERT( m_macCurrentPortStateHelper == NULL ) ;
m_macCurrentPortStateHelper = help ;
#endif
SetClip( (RgnHandle) m_macCurrentClipRgn);
#if ! wxMAC_EXPERIMENTAL_DC
m_macFontInstalled = false ;
m_macBrushInstalled = false ;
m_macPenInstalled = false ;
#endif
}
void wxDC::MacCleanupPort(wxMacPortStateHelper* help) const
{
#ifdef __WXDEBUG__
wxASSERT( m_macCurrentPortStateHelper == help ) ;
m_macCurrentPortStateHelper = NULL ;
#endif
if ( m_macATSUIStyle )
{
::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
m_macATSUIStyle = NULL ;
}
if ( m_macAliasWasEnabled )
{
SetAntiAliasedTextEnabled(m_macFormerAliasState, m_macFormerAliasSize);
m_macAliasWasEnabled = false ;
}
if ( m_macForegroundPixMap )
{
Pattern blackColor ;
::PenPat(GetQDGlobalsBlack(&blackColor));
DisposePixPat( (PixPatHandle) m_macForegroundPixMap ) ;
m_macForegroundPixMap = NULL ;
}
if ( m_macBackgroundPixMap )
{
Pattern whiteColor ;
::BackPat(GetQDGlobalsWhite(&whiteColor));
DisposePixPat( (PixPatHandle) m_macBackgroundPixMap ) ;
m_macBackgroundPixMap = NULL ;
}
}
void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
{
wxCHECK_RET( Ok(), wxT("wxDC::DoDrawBitmap - invalid DC") );
wxCHECK_RET( bmp.Ok(), wxT("wxDC::DoDrawBitmap - invalid bitmap") );
wxMacFastPortSetter helper(this) ;
wxCoord xx = XLOG2DEVMAC(x);
wxCoord yy = YLOG2DEVMAC(y);
wxCoord w = bmp.GetWidth();
wxCoord h = bmp.GetHeight();
wxCoord ww = XLOG2DEVREL(w);
wxCoord hh = YLOG2DEVREL(h);
// Set up drawing mode
short mode = (m_logicalFunction == wxCOPY ? srcCopy :
//m_logicalFunction == wxCLEAR ? WHITENESS :
//m_logicalFunction == wxSET ? BLACKNESS :
m_logicalFunction == wxINVERT ? hilite :
//m_logicalFunction == wxAND ? MERGECOPY :
m_logicalFunction == wxOR ? srcOr :
m_logicalFunction == wxSRC_INVERT ? notSrcCopy :
m_logicalFunction == wxXOR ? srcXor :
m_logicalFunction == wxOR_REVERSE ? notSrcOr :
//m_logicalFunction == wxAND_REVERSE ? SRCERASE :
//m_logicalFunction == wxSRC_OR ? srcOr :
//m_logicalFunction == wxSRC_AND ? SRCAND :
srcCopy );
GWorldPtr maskworld = NULL ;
GWorldPtr bmapworld = MAC_WXHBITMAP( bmp.GetHBITMAP((WXHBITMAP*)&maskworld) );
PixMapHandle bmappixels ;
// Set foreground and background colours (for bitmaps depth = 1)
if (bmp.GetDepth() == 1)
{
RGBColor fore = MAC_WXCOLORREF(m_textForegroundColour.GetPixel());
RGBColor back = MAC_WXCOLORREF(m_textBackgroundColour.GetPixel());
RGBForeColor(&fore);
RGBBackColor(&back);
}
else
{
RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF } ;
RGBColor black = { 0, 0, 0 } ;
RGBForeColor( &black ) ;
RGBBackColor( &white ) ;
}
bmappixels = GetGWorldPixMap( bmapworld ) ;
wxCHECK_RET(LockPixels(bmappixels),
wxT("wxDC::DoDrawBitmap - failed to lock pixels"));
Rect source = { 0, 0, h, w };
Rect dest = { yy, xx, yy + hh, xx + ww };
if ( useMask && maskworld )
{
if ( LockPixels(GetGWorldPixMap(MAC_WXHBITMAP(maskworld))))
{
CopyDeepMask
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -