osxcontext.cpp

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

CPP
2,398
字号
bool OSXContext::isTextAlignedToBaseline(){	return false;}double OSXContext::getLayoutWidth( ATSUTextLayout layout ){	ATSUTextMeasurement width = 0;	OSStatus status = ATSUGetLayoutControl( layout,											kATSULineWidthTag,											sizeof(ATSUTextMeasurement),											&width, NULL );	if ( status == noErr ) {		return (double)width;	}	else {		//throw exception ??	}	return -1.0;}void OSXContext::atsuDrawTextInBox(	const VCF::Rect& rect, const long& drawOptions ){	OSStatus 			err = noErr;	UniCharArrayOffset	textOffset = 0;	UniCharCount		textLength = 0;	UniCharArrayOffset*	lineEndOffsets = NULL;	bool failed = false;	// the the range of text to be drawn	err = ATSUGetTextLocation (textLayout_, NULL, NULL, &textOffset, &textLength, NULL);	if (err == noErr) {		UniCharArrayOffset lineStartOffset = textOffset;		UniCharArrayOffset lineEndOffset = 0;		FixedPointNumber xPos = rect.left_;		double EMTextHeight = getTextHeight("EM");		ATSUTextMeasurement	yPos = VCF_INTTOFIXED((int) ( rect.top_ + EMTextHeight ));		ATSUTextMeasurement	lineStart = xPos;		ATSUTextMeasurement	lineEnd = VCF_INTTOFIXED((int)rect.right_);		ATSUTextMeasurement	lineWidth = 0;		//at the moment we are not taking text angle into account		Fixed textAngle = 0;		ItemCount lineCount = 0;		ItemCount softBreakCount = 0;		ATSUTextMeasurement	maxAscent = 0, maxDescent = 0;		ulong32 ln = 0;		// check for linewidth set as a layout control		//lineWidth = getLayoutWidth( textLayout_ );		//	if there is no layout control set for width		//	then set it using the box bounds		if (lineWidth == 0) {			lineWidth = lineEnd - lineStart;		}		//	Break and measure each line to determine the max ascent and descent;		//	This is needed because things that end up on different lines		//	could interact to affect the line height when they're on the same line.		//	To get the best value we break the lines first, then measure each		//	line and find the max ascent and descent.		while (lineStartOffset < textOffset + textLength) {			ATSUTextMeasurement		ascent = 0, descent = 0;			// set the soft breaks, we will use them later			err = ATSUBreakLine(textLayout_, lineStartOffset, lineWidth, true, &lineEndOffset);			if ( err != noErr ) {				failed = true;				//printf ( "err: %d, ATSUBreakLine()\n", (int)err );				goto EXIT;			}			// @@@ If you want leave lines that are terminated with a hard break unjustified, this is a			// good place to set the individual line control to do that.#if (ATSU_TARG_VERSION >= ATSU_1_1)			// ATSUGetGlyphBounds is better than ATSUMeasureText if you've got any interesting feature			// such as justification turned on. The former will do the layout exactly as it will be drawn and cache			// the result, so things will be faster overall. ATSUMeasureText will turn off justification and end up doing			// an "extra" layout operation.			{				ATSTrapezoid	glyphBounds;	// one should be enough when we're asking for the whole line.				err = ATSUGetGlyphBounds( textLayout_, 0, 0, lineStartOffset, lineEndOffset - lineStartOffset, kATSUseFractionalOrigins,												1, &glyphBounds, NULL );				if ( err != noErr ) {					failed = true;					printf ( "err: %d, ATSUGetGlyphBounds()\n", (int)err );					goto EXIT;				}				// The top and bottom of the bounds should be parallel to the baseline. You might want to check that.				if (textAngle == 0) {					ascent = -glyphBounds.upperLeft.y;					descent = glyphBounds.lowerLeft.y;				} else {					// This looks strange, but the box you get is rotated, so "upper left" relative to the line is "upper right" in absolute terms.					ascent = glyphBounds.upperLeft.x;					descent = -glyphBounds.lowerLeft.x;				}			}#else			err = ATSUMeasureText(textLayout_, lineStartOffset, lineEndOffset - lineStartOffset, NULL, NULL, &ascent, &descent);			if ( err != noErr ) {				failed = true;				printf ( "err: %d, ATSUMeasureText()\n", err );				goto EXIT;			}#endif			if (ascent > maxAscent)				maxAscent = ascent;			if (descent > maxDescent)				maxDescent = descent;			lineStartOffset = lineEndOffset;			lineCount++;		}		lineEndOffsets = (UniCharArrayOffset*) NewPtr(lineCount * sizeof(UniCharArrayOffset));		err = MemError();		if ( err != noErr ) {			failed = true;			printf ( "err: %d, MemError()\n", (int)err );			goto EXIT;		}		err = ATSUGetSoftLineBreaks(	textLayout_,											textOffset,											textLength,											lineCount,											lineEndOffsets,											&softBreakCount);		//	assert that the number of soft breaks is always one less than the number of lines		//	since ATSUBreakLine does not insert a softbreak at the end of the text.		if ( (err != noErr) || (softBreakCount != (lineCount - 1)) ) {			failed = true;			printf ( "err: %d, ATSUGetSoftLineBreaks()\n", (int)err );			goto EXIT;		}		lineEndOffsets[softBreakCount] = textOffset + textLength;		lineStartOffset = textOffset;		// @@@ If maxAscent or maxDescent are not integers, this code may produce uneven line spacing. It will also		// not necessarily match the line height used by ATSUI when highlighting. ATSUI highlighting uses		// vcf_FixedToInt( baseline - ascent ) for the top of the box and vcf_FixedToInt( baseline + descent ) for the bottom.		// Any other combination of reflection and rounding can result in one-pixel gaps and overlaps.		// If you're using ATSUGetGlyphBounds above, you could ask for kATSUseDeviceOrigins to have ATSUI do this transformation for you.		//	draw each line		if ( drawOptions & GraphicsContext::tdoBottomAlign ) {			yPos = VCF_INTTOFIXED( rect.bottom_ + EMTextHeight );			yPos -=	(lineCount * (maxAscent+maxDescent));		}		else if ( drawOptions & GraphicsContext::tdoCenterVertAlign ) {			yPos = VCF_INTTOFIXED( rect.top_ + rect.getHeight()/2.0 + EMTextHeight );			yPos -=	((lineCount * (maxAscent+maxDescent))/2);		}		for (ln = 0; ln < lineCount; ln++) {			lineEndOffset = lineEndOffsets[ln];			err = ATSUDrawText( textLayout_,										lineStartOffset,										lineEndOffset - lineStartOffset,										xPos,										yPos*-1);			if ( err != noErr ) {				failed = true;				printf ( "err: %d, ATSUDrawText() failed in OSXContect::atsuDrawTextInBox()\n", (int)err );				goto EXIT;			}			lineStartOffset = lineEndOffset;			yPos += maxAscent;			yPos += maxDescent;		}	}EXIT:	if ( failed ) {		//throw exception ??		printf( "\n\nWe Blewit !\n\n" );	}	if (lineEndOffsets != NULL)  {		DisposePtr((char*)lineEndOffsets);	}}void OSXContext::setClippingPath( Path* clippingPath ){	if ( NULL != clippingPath ) {		std::vector<PathPoint> points;				if ( clippingPath->getPoints( points, NULL ) ) {				CGMutablePathRef  pathRef = CGPathCreateMutable();				PathPoint p2, c1, c2;									std::vector<PathPoint>::iterator it = points.begin();			while ( it != points.end() ) {				PathPoint& pt = *it;				switch ( pt.type_ ){					case PathPoint::ptMoveTo: {						CGPathMoveToPoint( pathRef, NULL, pt.point_.x_ + origin_.x_, pt.point_.y_ + origin_.y_);					}					break;					case PathPoint::ptLineTo: {						CGPathAddLineToPoint( pathRef, NULL, pt.point_.x_+origin_.x_, pt.point_.y_ + origin_.y_);					}					break;					case PathPoint::ptQuadTo: {											it++;						c1 = *it;						it++;						c2 = *it;						it++;						p2 = *it;																		if ( it == points.begin() ) {							CGPathMoveToPoint( pathRef, NULL, pt.point_.x_, pt.point_.y_);							CGPathAddCurveToPoint( pathRef, NULL, 													c1.point_.x_ + origin_.x_,													c1.point_.y_ + origin_.y_,													c2.point_.x_ + origin_.x_,													c2.point_.y_ + origin_.y_,													p2.point_.x_ + origin_.x_,													p2.point_.y_ + origin_.y_ );						}						else {							CGPathAddCurveToPoint( pathRef, NULL, 													c1.point_.x_ + origin_.x_,													c1.point_.y_ + origin_.y_,													c2.point_.x_ + origin_.x_,													c2.point_.y_ + origin_.y_,													p2.point_.x_ + origin_.x_,													p2.point_.y_ + origin_.y_ );						}					}					break;					case PathPoint::ptCubicTo: {					}					break;					case PathPoint::ptClose: {						CGPathCloseSubpath( pathRef );											}					break;				}								it ++;			}						CGContextSaveGState( contextID_ );						CGContextBeginPath ( contextID_ );						CGContextAddPath( contextID_, pathRef );						CGContextClosePath(contextID_);						CGContextClip( contextID_ );						CGPathRelease( pathRef );					}	}	else {		CGContextRestoreGState( contextID_ );	}}void OSXContext::setClippingRect( Rect* clipRect ){		if ( NULL != clipRect ) {		if ( clipRect->isNull() || clipRect->isEmpty() ) {			//CGContextRestoreGState( contextID_ );				//CGContextRestoreGState( contextID_ );				}		else {			Rect tmpClipRect = *clipRect;			tmpClipRect.offset( origin_.x_, origin_.y_ );						OSXRect r = &tmpClipRect;						//CGContextSaveGState( contextID_ );			CGContextClipToRect( contextID_, r );		}	}	else {		//CGContextRestoreGState( contextID_ );			}}void OSXContext::drawThemeSelectionRect( Rect* rect, DrawUIState& state ){	CGContextSaveGState( contextID_ );		Color* stroke = Color::getColor("gray100");	Color* fill = Color::getColor("gray128");		CGContextSetAlpha( contextID_, 0.2 );		Rect tmp = *rect;	tmp.offset( origin_.x_, origin_.y_ );	OSXRect r = &tmp;		CGContextSetLineWidth( contextID_, 1.0 );	CGContextSetRGBStrokeColor( contextID_, stroke->getRed(), stroke->getGreen(),										stroke->getBlue(), 1.0 );											CGContextSetRGBFillColor( contextID_, fill->getRed(), fill->getGreen(),										fill->getBlue(), 1.0 );										    CGContextBeginPath( contextID_ );	CGContextAddRect( contextID_, r );	CGContextClosePath( contextID_ );	CGContextDrawPath ( contextID_, kCGPathFillStroke );		//CGContextFillPath ( contextID_ );		CGContextRestoreGState( contextID_ );	}void OSXContext::drawThemeFocusRect( Rect* rect, DrawUIState& state ){	Rect tmp = *rect;	tmp.offset( origin_.x_, origin_.y_ );	OSXRect r = &tmp;    DrawThemeFocusRect( r, state.isFocused() );}void OSXContext_drawThemeButtonText( const ::Rect * bounds, ThemeButtonKind kind, 										const ThemeButtonDrawInfo * info, UInt32 userData,										SInt16 depth, Boolean isColorDev ){		ButtonState* state = (ButtonState*)userData;	CFTextString cfStr;	cfStr = state->buttonCaption_;	::Point textSize;	SInt16 baseLine;	GetThemeTextDimensions( cfStr, kThemePushButtonFont, info->state, FALSE, &textSize, &baseLine );	::Rect adjustedBounds = *bounds;	adjustedBounds.top += ((bounds->bottom-bounds->top)/2) - (textSize.v/2);	DrawThemeTextBox( cfStr, kThemePushButtonFont, info->state, FALSE, &adjustedBounds, teCenter, NULL );}void OSXContext::drawThemeButtonRect( Rect* rect, ButtonState& state, Rect* captionRect ){	Rect tmp = *rect;	tmp.offset( origin_.x_, origin_.y_ );	OSXRect r = &tmp;	    ThemeButtonDrawInfo btnInfo;	btnInfo.state = kThemeStateInactive ;		if ( state.isPressed() && (state.isActive() && state.isEnabled()) ) {		btnInfo.state |= kThemeStatePressed;	}		if ( state.isActive() && state.isEnabled() ) {		btnInfo.state |= kThemeStateActive;	}		btnInfo.value = kThemeButtonOff;	btnInfo.adornment = kThemeAdornmentNone;		if ( state.isFocused() ) {		btnInfo.adornment |= kThemeAdornmentFocus;	}		if ( state.isDefaultButton() && (state.isActive() && state.isEnabled()) ) {		btnInfo.state |= kThemeStatePressed;	}   /*	printf( "state.isPressed() : %s\n", state.isPressed() ? "true" : "false"  );	printf( "state.isActive() : %s\n", state.isActive() ? "true" : "false"  );	printf( "state.isEnabled() : %s\n", state.isEnabled() ? "true" : "false"  );	printf( "state.isFocused() : %s\n", state.isFocused() ? "true" : "false"  );	printf( "state.isDefaultButton() : %s\n", state.isDefaultButton() ? "true" : "false"  );	printf( "button text : %s\n", state.buttonCaption_.ansi_c_str() );	printf( "--------------------------------------------------------\n\n");*/	ThemeButtonDrawUPP btnDrawUPP = NewThemeButtonDrawUPP(OSXContext_drawThemeButtonText);	    DrawThemeButton( r, kThemePushButton, &btnInfo, NULL, NULL, btnDrawUPP, (UInt32)&state );		DisposeThemeButtonDrawUPP(btnDrawUPP);}void OSXContext::drawThemeButtonFocusRect( Rect* rect ){}void OSXContext::drawThemeCheckboxRect( Rect* rect, ButtonState& state ){	Rect tmp = *rect;	tmp.offset( origin_.x_, origin_.y_ );	OSXRect r = &tmp;	    ThemeButtonDrawInfo btnInfo;	btnInfo.state = kThemeStateInactive ;		btnInfo.value = kThemeButtonOff;		if ( state.isPressed() ) {		btnInfo.state |= kThemeStatePressed;	}		if ( state.isToggled() ) {		btnInfo.value = kThemeButtonOn;	}		if ( state.isActive() && state.isEnabled() ) {		btnInfo.state |= kThemeStateActive;	}			btnInfo.adornment = kThemeAdornmentNone;		if ( state.isFocused() ) {		btnInfo.adornment |= kThemeAdornmentFocus;	}	        	ThemeButtonDrawUPP btnDrawUPP = NewThemeButtonDrawUPP(OSXContext_drawThemeButtonText);	    DrawThemeButton( r, kThemeCheckBox, &btnInfo, NULL, NULL, btnDrawUPP, (UInt32)&state );		DisposeThemeButtonDrawUPP(btnDrawUPP);}void OSXContext::drawThemeRadioButtonRect( Rect* rect, ButtonState& state ){	Rect tmp = *rect;	tmp.offset( origin_.x_, origin_.y_ );	OSXRect r = &tmp;	    ThemeButtonDrawInfo btnInfo;	btnInfo.state = kThemeStateInactive ;		btnInfo.value = kThemeButtonOff;		if ( state.isPressed() ) {		btnInfo.state |= kThemeStatePressed;	}		if ( state.isToggled() ) {		btnInfo.value = kThemeButtonOn;

⌨️ 快捷键说明

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