首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用核心文本获取最后一个字符的缩写

如何使用核心文本获取最后一个字符的缩写
EN

Stack Overflow用户
提问于 2014-02-21 15:37:17
回答 1查看 1.4K关注 0票数 5

我有一个NSAttributedString,一个rect来画整个字符串,我想得到最后一个字符的简写,就像下面的图片一样,如何使用核心文本得到那个?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-27 14:55:53

特别是使用CoreText,下面是一个应该工作的函数(代码中有一些注释解释了正在发生的事情):

代码语言:javascript
复制
- (CGRect)lastCharacterRectForAttributedString:(NSAttributedString *)attributedString drawingRect:(CGRect)drawingRect
{
    // Start by creating a CTFrameRef using the attributed string and rect.
    CTFrameRef textFrame = NULL;
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attributedString));
    CGPathRef drawingPath = CGPathCreateWithRect(drawingRect, NULL);
    textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attributedString length]), drawingPath, NULL);
    CFRelease(framesetter);
    CFRelease(drawingPath);

    // Line origins can be obtained from the CTFrameRef. Get the final one.
    CGPoint finalLineOrigin;
    CFArrayRef lines = CTFrameGetLines(textFrame);
    if (CFArrayGetCount(lines) == 0) { // Safety check
        CFRelease(textFrame);
        return CGRectNull;
    }
    const CFIndex finalLineIdx = CFArrayGetCount(lines) - 1;
    CTFrameGetLineOrigins(textFrame, CFRangeMake(finalLineIdx, 1), &finalLineOrigin);

    // Get the glyph runs from the final line. Get the last glyph position from the final run.
    CGPoint glyphPosition;
    CFArrayRef runs = CTLineGetGlyphRuns(CFArrayGetValueAtIndex(lines, finalLineIdx));
    if (CFArrayGetCount(runs) == 0) { // Safety check
        CFRelease(textFrame);
        return CGRectNull;
    }
    CTRunRef finalRun = CFArrayGetValueAtIndex(runs, CFArrayGetCount(runs) - 1);
    if (CTRunGetGlyphCount(finalRun) == 0) { // Safety check
        CFRelease(textFrame);
        return CGRectNull;
    }
    const CFIndex lastGlyphIdx = CTRunGetGlyphCount(finalRun) - 1;
    CTRunGetPositions(finalRun, CFRangeMake(lastGlyphIdx, 1), &glyphPosition);

    // The bounding box of the glyph itself is extracted from the font.
    CGRect glyphBounds;
    CFDictionaryRef runAttributes = CTRunGetAttributes(finalRun);
    CTFontRef font = CFDictionaryGetValue(runAttributes, NSFontAttributeName);
    CGGlyph glyph;
    CTRunGetGlyphs(finalRun, CFRangeMake(lastGlyphIdx, 1), &glyph);
    CTFontGetBoundingRectsForGlyphs(font, kCTFontDefaultOrientation, &glyph, &glyphBounds, 1);

    // Option 1 - The rect you've drawn in your question isn't tight to the final character; it looks approximately the height of the line. If that's what you're after:
    CGRect lineBounds = CTLineGetBoundsWithOptions(CFArrayGetValueAtIndex(lines, finalLineIdx), 0);
    CGRect desiredRect = CGRectMake(
                                    CGRectGetMinX(drawingRect) + finalLineOrigin.x + glyphPosition.x + CGRectGetMinX(glyphBounds),
                                    CGRectGetMinY(drawingRect) + (CGRectGetHeight(drawingRect) - (finalLineOrigin.y + CGRectGetMaxY(lineBounds))),
                                    CGRectGetWidth(glyphBounds),
                                    CGRectGetHeight(lineBounds)
                                    );
    // Option 2 - If you want a rect that closely bounds the final character, use this:
    /*
    CGRect desiredRect = CGRectMake(
                                    CGRectGetMinX(drawingRect) + finalLineOrigin.x + glyphPosition.x + CGRectGetMinX(glyphBounds),
                                    CGRectGetMinY(drawingRect) + (CGRectGetHeight(drawingRect) - (finalLineOrigin.y + glyphPosition.y + CGRectGetMaxY(glyphBounds))),
                                    CGRectGetWidth(glyphBounds),
                                    CGRectGetHeight(glyphBounds)
                                    );
    */

    CFRelease(textFrame);

    return desiredRect;
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21938643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档