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 + -
显示快捷键?