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