osxcontext.cpp

来自「这是VCF框架的代码」· C++ 代码 · 共 2,398 行 · 第 1/5 页

CPP
2,398
字号
//OSXContext.cpp/*Copyright 2000-2004 The VCF Project.Please see License.txt in the top level directorywhere you installed the VCF.*/#include "vcf/GraphicsKit/GraphicsKit.h"#include "vcf/GraphicsKit/GraphicsKitPrivate.h"#include "vcf/FoundationKit/VCFMath.h"#include "vcf/GraphicsKit/DrawUIState.h"using namespace VCF;OSXContext::OSXContext():	contextID_(nil),    grafPort_(0),	inMemoryImage_(nil),    imgWidth_(0),    imgHeight_(0),	context_(NULL),	currentDrawingOperation_(0),	textLayout_(nil),    xorModeOn_(false),	lastPrimitive_(OSXContext::lpNone),	antialiasingOn_(true){	init();}OSXContext::OSXContext( const unsigned long& width, const unsigned long& height ):	contextID_(nil),    grafPort_(0),	inMemoryImage_(nil),    imgWidth_(width),    imgHeight_(height),	context_(NULL),	currentDrawingOperation_(0),	textLayout_(nil),    xorModeOn_(false),	lastPrimitive_(OSXContext::lpNone),	antialiasingOn_(true){	//allocate a RGBA buffer for use    inMemoryImage_ = new unsigned char[imgWidth_ * imgHeight_ * 4];	init();}OSXContext::OSXContext( OSHandleID contextID ):	contextID_(0),    grafPort_((GrafPtr)contextID),	inMemoryImage_(nil),    imgWidth_(0),    imgHeight_(0),	context_(NULL),	currentDrawingOperation_(0),	textLayout_(nil),    xorModeOn_(false),	lastPrimitive_(OSXContext::lpNone),	antialiasingOn_(true){	init();}OSXContext::~OSXContext(){	if ( nil != textLayout_ ) {		ATSUDisposeTextLayout( textLayout_ );	}    CGContextRelease( contextID_);    if ( NULL != inMemoryImage_ ) {        delete [] inMemoryImage_;        inMemoryImage_ = NULL;        DisposeGWorld( grafPort_ );    }	contextID_ = nil;}void OSXContext::setContext( GraphicsContext* context ){	context_ = context;}GraphicsContext* OSXContext::getContext(){	return context_;}OSHandleID OSXContext::getContextID(){	return (OSHandleID)grafPort_;}void OSXContext::setContextID( OSHandleID handle ){    if ( NULL != inMemoryImage_ ) {        delete [] inMemoryImage_;        inMemoryImage_ = 0;        imgWidth_ = 0;        imgHeight_ = 0;        DisposeGWorld( grafPort_ );		    }	if ( NULL != grafPort_ ) {		CGContextRelease( contextID_);		contextID_ = NULL;    }	grafPort_ = (GrafPtr)handle;    init();}void OSXContext::setPortFromImage( GrafPtr port, uint32 width, uint32 height ){				grafPort_ = port;	ownerRect_.setRect( 0, 0, width, height );		if ( NULL != contextID_ ) {		CGContextRelease( contextID_);	}			CreateCGContextForPort( grafPort_, &contextID_);				//Note the absence of a transform! apparently we don't need to for 	//image based CG's		if ( nil == textLayout_ ) {		ATSUCreateTextLayout( &textLayout_ );	}		ATSUAttributeTag        cgTags[] = {kATSUCGContextTag};	ByteCount               cgSize[] = {sizeof (contextID_)};	ATSUAttributeValuePtr   cgValue[] = {&contextID_};	OSStatus err = ATSUSetLayoutControls (textLayout_,										  1,										  cgTags,										  cgSize,										  cgValue);	if ( err != noErr ) {		throw RuntimeException( MAKE_ERROR_MSG_2("ATSUSetLayoutControls failed.") );	}	}void OSXContext::setCGContext( CGContextRef cgRef, GrafPtr port, const Rect& ownerRect  ){	if ( NULL != inMemoryImage_ ) {        delete [] inMemoryImage_;        inMemoryImage_ = 0;        imgWidth_ = 0;        imgHeight_ = 0;        DisposeGWorld( grafPort_ );    }	ownerRect_ = ownerRect;	contextID_ = cgRef;	grafPort_ = NULL;	if ( NULL != inMemoryImage_ ) {        //allocate a new gworld        GWorldPtr newGworld = 0;        int bitsPerPix = 32;        int componentCount = 4;        int bytesPerRow = (imgWidth_ * (bitsPerPix/componentCount) * componentCount) / 8;        ::Rect imgRect;        imgRect.left = 0;        imgRect.top = 0;        imgRect.right = imgWidth_;        imgRect.bottom = imgHeight_;        OSStatus err = 0;        err = NewGWorldFromPtr( &newGworld,                            k32RGBAPixelFormat,                            &imgRect,                            NULL,                            NULL,                            0,                            (char*)inMemoryImage_,                            bytesPerRow );        if ( noErr == err ) {            grafPort_ = newGworld;//            printf( "NewGWorldFromPtr() succeeded, grafPort_: %p\n", grafPort_ );        }        else {            throw RuntimeException( MAKE_ERROR_MSG_2("NewGWorldFromPtr() failed to allocate GWorld") );        }    }	grafPort_ = port;	if ( nil == textLayout_ ) {		ATSUCreateTextLayout( &textLayout_ );	}	if ( NULL != contextID_ ) {		ATSUAttributeTag        cgTags[] = {kATSUCGContextTag};		ByteCount               cgSize[] = {sizeof (contextID_)};		ATSUAttributeValuePtr   cgValue[] = {&contextID_};		OSStatus err = ATSUSetLayoutControls (textLayout_,											  1,											  cgTags,											  cgSize,											  cgValue);		if ( err != noErr ) {			throw RuntimeException( MAKE_ERROR_MSG_2("ATSUSetLayoutControls failed.") );		}	}}void OSXContext::init(){    origin_.x_ = 0;	origin_.y_ = 0;		if ( NULL != inMemoryImage_ ) {        //allocate a new gworld        GWorldPtr newGworld = 0;        int bitsPerPix = 32;        int componentCount = 4;        int bytesPerRow = (imgWidth_ * (bitsPerPix/componentCount) * componentCount) / 8;        ::Rect imgRect;        imgRect.left = 0;        imgRect.top = 0;        imgRect.right = imgWidth_;        imgRect.bottom = imgHeight_;        OSStatus err = 0;        err = NewGWorldFromPtr( &newGworld,                            k32RGBAPixelFormat,                            &imgRect,                            NULL,                            NULL,                            0,                            (char*)inMemoryImage_,                            bytesPerRow );        if ( noErr == err ) {            grafPort_ = newGworld;//            printf( "NewGWorldFromPtr() succeeded, grafPort_: %p\n", grafPort_ );        }        else {            throw RuntimeException( MAKE_ERROR_MSG_2("NewGWorldFromPtr() failed to allocate GWorld") );        }    }    if ( NULL != grafPort_ ) {        CreateCGContextForPort( grafPort_, &contextID_);		//CGContextSaveGState( contextID_ );		::Rect portBounds;        GetPortBounds( grafPort_, &portBounds );        CGContextTranslateCTM(contextID_, 0,                                        (float)(portBounds.bottom - portBounds.top));        CGContextScaleCTM(contextID_, 1, -1);		if( nil == textLayout_ ) { //only do this once			ATSUCreateTextLayout( &textLayout_ );		}		ATSUAttributeTag        cgTags[] = {kATSUCGContextTag};		ByteCount               cgSize[] = {sizeof (contextID_)};		ATSUAttributeValuePtr   cgValue[] = {&contextID_};		OSStatus err = ATSUSetLayoutControls (textLayout_,											  1,											  cgTags,											  cgSize,											  cgValue);		if ( err != noErr ) {			throw RuntimeException( MAKE_ERROR_MSG_2("ATSUSetLayoutControls failed.") );		}	}}void OSXContext::textAt( const VCF::Rect& bounds, const String & text, const long& drawOptions ){    VCF::Rect offsetBounds = bounds;    offsetBounds.offset( origin_ );	//tdoWordWrap=1,	//tdoLeftAlign=2,	//tdoCenterHorzAlign=4,	//tdoRightAlign=8,	//tdoBottomAlign=16,	//tdoCenterVertAlign=32,	//tdoTopAlign=64		ATSUSetTextPointerLocation( textLayout_,								text.c_str(),								kATSUFromTextBeginning,								kATSUToTextEnd,								text.length() );	//CFTextString cfStr;	//cfStr = text;    Font* ctxFont = context_->getCurrentFont();	FontPeer* fontImpl = ctxFont->getFontPeer();		ATSUStyle fontStyle = (ATSUStyle)fontImpl->getFontHandleID();		ATSUSetRunStyle( textLayout_, fontStyle, 0, text.length() );		OSStatus err = 0;		ATSUAttributeTag tag[] = {kATSULineFlushFactorTag};	ByteCount tagSize = sizeof(Fract);	Fract orginalVal = 0;	Fract val = 0;	ByteCount actualSz[] = {sizeof(Fract)};			if ( drawOptions & GraphicsContext::tdoLeftAlign ) {		val = kATSUStartAlignment;	}	else if ( drawOptions & GraphicsContext::tdoRightAlign ) {		val = kATSUEndAlignment;	}	else if ( drawOptions & GraphicsContext::tdoCenterHorzAlign ) {		val = kATSUCenterAlignment;	}		ATSUAttributeValuePtr attrVals[] = {&val};			err = ATSUGetLayoutControl( textLayout_, tag[0], tagSize, 										(ATSUAttributeValuePtr)&orginalVal, &actualSz[0] );		if ( err != noErr ) {		//StringUtils::trace( "ATSUGetLayoutControl(kATSULineFlushFactorTag) failed" );	}		err = ATSUSetLayoutControls( textLayout_, 1, tag, actualSz, attrVals );	if ( err != noErr ) {		//StringUtils::trace( "ATSUSetLayoutControls(kATSULineFlushFactorTag) failed" );	}					if ( GraphicsContext::tdoWordWrap & drawOptions ) {		//do word wrap		VCF::Rect r = offsetBounds;		atsuDrawTextInBox( r, drawOptions );	}	else {		double textHeight = getTextHeight("EM");				setLayoutWidth( textLayout_, 0 );		FixedPointNumber x =  offsetBounds.left_;		FixedPointNumber lineWidth =  offsetBounds.getWidth();		FixedPointNumber y = ((offsetBounds.top_ + textHeight)*-1.0);				if ( drawOptions & GraphicsContext::tdoBottomAlign ) {			y = ((offsetBounds.bottom_/* + textHeight*/) *-1.0);		}		else if ( drawOptions & GraphicsContext::tdoCenterVertAlign ) {			y = ((offsetBounds.top_ + offsetBounds.getHeight()/2.0 + textHeight/2.0 ) *-1.0 );		}						UniCharArrayOffset lineEndOffset;		err = ATSUBreakLine(textLayout_, kATSUFromTextBeginning, lineWidth, true, &lineEndOffset);				if ( noErr != err ) {			//StringUtils::trace( "ATSUBreakLine() failed" );		}				err = ATSUDrawText( textLayout_,							kATSUFromTextBeginning,							lineEndOffset,							x,  y );		if ( noErr != err ) {			StringUtils::trace( "ATSUDrawText() failed" );		}	}	attrVals[0] = &orginalVal;	//reset original tag vals	ATSUSetLayoutControls( textLayout_, 1, tag, actualSz, attrVals );}void OSXContext::setLayoutWidth( ATSUTextLayout layout, double width ){	FixedPointNumber fwidth = width;	ATSUTextMeasurement textWidth = fwidth;	ATSUAttributeTag tag = kATSULineWidthTag;	ByteCount count = sizeof(ATSUTextMeasurement);	ATSUAttributeValuePtr ptr = &textWidth;	ATSUSetLayoutControls( layout, 1, &tag, &count, &ptr );}VCF::Size OSXContext::getLayoutDimensions( const String& text ){	int length = text.length();	if ( NULL == textLayout_ ) {		return Size();	}		ATSUTextLayout tmpTextLayout = NULL;	OSStatus err = ATSUCreateAndCopyTextLayout( textLayout_, &tmpTextLayout );	if ( err != noErr ) {		String msg = StringUtils::format( Format("ATSUCreateAndCopyTextLayout failed, err: %d, textLayout_: %p, tmpTextLayout: %p") % err % textLayout_ % tmpTextLayout );		throw RuntimeException( MAKE_ERROR_MSG_2(msg) );	}			ATSUSetTextPointerLocation( tmpTextLayout, text.c_str(),                                 kATSUFromTextBeginning, 								kATSUToTextEnd, 								length );														setLayoutWidth( tmpTextLayout, 0 );			Font* ctxFont = context_->getCurrentFont();	FontPeer* fontImpl = ctxFont->getFontPeer();	ATSUStyle fontStyle = (ATSUStyle)fontImpl->getFontHandleID();													ATSUSetRunStyle( tmpTextLayout, fontStyle, 0, length );			ItemCount actualBoundsReturned  = 1;	ATSTrapezoid bounds;																	ATSUGetGlyphBounds( tmpTextLayout, 0, 0, 0, length, kATSUseDeviceOrigins, 1, &bounds, &actualBoundsReturned );							VCF::Size result;	FixedPointNumber w = (Fixed)abs(bounds.upperLeft.x - bounds.upperRight.x);	result.width_ = w.asDouble();	FixedPointNumber h = (Fixed)(-bounds.upperLeft.y) + bounds.lowerLeft.y;	result.height_ = h.asDouble();		ATSUDisposeTextLayout( tmpTextLayout );		return  result;}double OSXContext::getTextWidth( const String& text ){	return getLayoutDimensions(text).width_;}double OSXContext::getTextHeight( const String& text ){	return getLayoutDimensions(text).height_;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?