📄 dccg.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: src/mac/carbon/dccg.cpp
// Purpose: wxDC class
// Author: Stefan Csomor
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id: dccg.cpp,v 1.46 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
#include "math.h"
// in case our functions were defined outside std, we make it known all the same
namespace std { }
using namespace std ;
#endif
#endif
#include "wx/mac/private.h"
IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
#ifndef wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
#define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
#endif
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
#if !defined( __DARWIN__ ) || defined(__MWERKS__)
#ifndef M_PI
const double M_PI = 3.14159265358979 ;
#endif
#endif
const double RAD2DEG = 180.0 / M_PI;
const short kEmulatedMode = -1 ;
const short kUnsupportedMode = -2 ;
extern TECObjectRef s_TECNativeCToUnicode ;
// TODO: update
// The textctrl implementation still needs that (needs what?) for the non-HIView implementation
//
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 ) ;
}
// minimal implementation only used for appearance drawing < 10.3
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) ;
}
//-----------------------------------------------------------------------------
// 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; }
//-----------------------------------------------------------------------------
// device context implementation
//
// more and more of the dc functionality should be implemented by calling
// the appropricate wxMacCGContext, but we will have to do that step by step
// also coordinate conversions should be moved to native matrix ops
//-----------------------------------------------------------------------------
// we always stock two context states, one at entry, to be able to preserve the
// state we were called with, the other one after changing to HI Graphics orientation
// (this one is used for getting back clippings etc)
wxMacCGPath::wxMacCGPath()
{
m_path = CGPathCreateMutable() ;
}
wxMacCGPath::~wxMacCGPath()
{
CGPathRelease( m_path ) ;
}
// opens (starts) a new subpath
void wxMacCGPath::MoveToPoint( wxCoord x1 , wxCoord y1 )
{
CGPathMoveToPoint( m_path , NULL , x1 , y1 ) ;
}
void wxMacCGPath::AddLineToPoint( wxCoord x1 , wxCoord y1 )
{
CGPathAddLineToPoint( m_path , NULL , x1 , y1 ) ;
}
void wxMacCGPath::AddQuadCurveToPoint( wxCoord cx1, wxCoord cy1, wxCoord x1, wxCoord y1 )
{
CGPathAddQuadCurveToPoint( m_path , NULL , cx1 , cy1 , x1 , y1 );
}
void wxMacCGPath::AddRectangle( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
{
CGRect cgRect = { { x , y } , { w , h } } ;
CGPathAddRect( m_path , NULL , cgRect ) ;
}
void wxMacCGPath::AddCircle( wxCoord x, wxCoord y , wxCoord r )
{
CGPathAddArc( m_path , NULL , x , y , r , 0.0 , 2 * M_PI , true ) ;
}
// closes the current subpath
void wxMacCGPath::CloseSubpath()
{
CGPathCloseSubpath( m_path ) ;
}
CGPathRef wxMacCGPath::GetPath() const
{
return m_path ;
}
wxMacCGContext::wxMacCGContext( CGrafPtr port )
{
m_qdPort = port ;
m_cgContext = NULL ;
}
wxMacCGContext::wxMacCGContext( CGContextRef cgcontext )
{
m_qdPort = NULL ;
m_cgContext = cgcontext ;
CGContextSaveGState( m_cgContext ) ;
CGContextSaveGState( m_cgContext ) ;
}
wxMacCGContext::wxMacCGContext()
{
m_qdPort = NULL ;
m_cgContext = NULL ;
}
wxMacCGContext::~wxMacCGContext()
{
if ( m_cgContext )
{
CGContextSynchronize( m_cgContext ) ;
CGContextRestoreGState( m_cgContext ) ;
CGContextRestoreGState( m_cgContext ) ;
}
if ( m_qdPort )
CGContextRelease( m_cgContext ) ;
}
void wxMacCGContext::Clip( const wxRegion ®ion )
{
// ClipCGContextToRegion ( m_cgContext, &bounds , (RgnHandle) dc->m_macCurrentClipRgn ) ;
}
void wxMacCGContext::StrokePath( const wxGraphicPath *p )
{
const wxMacCGPath* path = dynamic_cast< const wxMacCGPath*>( p ) ;
CGContextAddPath( m_cgContext , path->GetPath() ) ;
CGContextStrokePath( m_cgContext ) ;
}
void wxMacCGContext::DrawPath( const wxGraphicPath *p , int fillStyle )
{
const wxMacCGPath* path = dynamic_cast< const wxMacCGPath*>( p ) ;
CGPathDrawingMode mode = m_mode ;
if ( fillStyle == wxODDEVEN_RULE )
{
if ( mode == kCGPathFill )
mode = kCGPathEOFill ;
else if ( mode == kCGPathFillStroke )
mode = kCGPathEOFillStroke ;
}
CGContextAddPath( m_cgContext , path->GetPath() ) ;
CGContextDrawPath( m_cgContext , mode ) ;
}
void wxMacCGContext::FillPath( const wxGraphicPath *p , const wxColor &fillColor , int fillStyle )
{
const wxMacCGPath* path = dynamic_cast< const wxMacCGPath*>( p ) ;
CGContextSaveGState( m_cgContext ) ;
RGBColor col = MAC_WXCOLORREF( fillColor.GetPixel() ) ;
CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
CGPathDrawingMode mode = kCGPathFill ;
if ( fillStyle == wxODDEVEN_RULE )
mode = kCGPathEOFill ;
CGContextBeginPath( m_cgContext ) ;
CGContextAddPath( m_cgContext , path->GetPath() ) ;
CGContextClosePath( m_cgContext ) ;
CGContextDrawPath( m_cgContext , mode ) ;
CGContextRestoreGState( m_cgContext ) ;
}
wxGraphicPath* wxMacCGContext::CreatePath()
{
// make sure that we now have a real cgref, before doing
// anything with paths
CGContextRef cg = GetNativeContext() ;
cg = NULL ;
return new wxMacCGPath() ;
}
// in case we only got a QDPort only create a cgref now
CGContextRef wxMacCGContext::GetNativeContext()
{
if ( m_cgContext == NULL )
{
Rect bounds ;
GetPortBounds( (CGrafPtr) m_qdPort , &bounds ) ;
OSStatus status = CreateCGContextForPort((CGrafPtr) m_qdPort , &m_cgContext) ;
CGContextSaveGState( m_cgContext ) ;
wxASSERT_MSG( status == noErr , wxT("Cannot nest wxDCs on the same window") ) ;
CGContextTranslateCTM( m_cgContext , 0 , bounds.bottom - bounds.top ) ;
CGContextScaleCTM( m_cgContext , 1 , -1 ) ;
CGContextSaveGState( m_cgContext ) ;
SetPen( m_pen ) ;
SetBrush( m_brush ) ;
}
return m_cgContext ;
}
void wxMacCGContext::SetNativeContext( CGContextRef cg )
{
// we allow either setting or clearing but not replacing
wxASSERT( m_cgContext == NULL || cg == NULL ) ;
if ( cg )
CGContextSaveGState( cg ) ;
m_cgContext = cg ;
}
#pragma mark -
#pragma mark wxMacCGPattern, ImagePattern, HatchPattern classes
// CGPattern wrapper class: always allocate on heap, never call destructor
class wxMacCGPattern
{
public :
wxMacCGPattern() {}
// is guaranteed to be called only with a non-Null CGContextRef
virtual void Render( CGContextRef ctxRef ) = 0 ;
operator CGPatternRef() const { return m_patternRef ; }
protected :
virtual ~wxMacCGPattern()
{
// as this is called only when the m_patternRef is been released;
// don't release it again
}
static void _Render( void *info, CGContextRef ctxRef )
{
wxMacCGPattern* self = (wxMacCGPattern*) info ;
if ( self && ctxRef )
self->Render( ctxRef ) ;
}
static void _Dispose( void *info )
{
wxMacCGPattern* self = (wxMacCGPattern*) info ;
delete self ;
}
CGPatternRef m_patternRef ;
static const CGPatternCallbacks ms_Callbacks ;
} ;
const CGPatternCallbacks wxMacCGPattern::ms_Callbacks = { 0, &wxMacCGPattern::_Render, &wxMacCGPattern::_Dispose };
class ImagePattern : public wxMacCGPattern
{
public :
ImagePattern( const wxBitmap* bmp , CGAffineTransform transform )
{
wxASSERT( bmp && bmp->Ok() ) ;
Init( (CGImageRef) bmp->CGImageCreate() , transform ) ;
}
// ImagePattern takes ownership of CGImageRef passed in
ImagePattern( CGImageRef image , CGAffineTransform transform )
{
if ( image )
CFRetain( image ) ;
Init( image , transform ) ;
}
virtual void Render( CGContextRef ctxRef )
{
if (m_image != NULL)
HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image );
}
protected :
void Init( CGImageRef image, CGAffineTransform transform )
{
m_image = image ;
if ( m_image )
{
m_imageBounds = CGRectMake( 0.0, 0.0, (float)CGImageGetWidth( m_image ), (float)CGImageGetHeight( m_image ) ) ;
m_patternRef = CGPatternCreate(
this , m_imageBounds, transform ,
m_imageBounds.size.width, m_imageBounds.size.height,
kCGPatternTilingNoDistortion, true , &wxMacCGPattern::ms_Callbacks ) ;
}
}
~ImagePattern()
{
if ( m_image )
CGImageRelease( m_image ) ;
}
CGImageRef m_image ;
CGRect m_imageBounds ;
} ;
class HatchPattern : public wxMacCGPattern
{
public :
HatchPattern( int hatchstyle, CGAffineTransform transform )
{
m_hatch = hatchstyle ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -