如何正确确定属性字符串的宽度

时间:2010-08-31 02:07:35

标签: objective-c cocoa macos nsattributedstring nslayoutmanager

我想做什么:使用NSLayoutManager布局文本,并将其NSTextContainer设置为字符串数组中最宽字符串(字形)的宽度。

我的问题是:确定总'字形宽度'的方法似乎不正确,因为当我渲染它包装的文本时。

我使用带有Monaco 12点字体的32个字符的字符串进行了实验,并且长度报告为224.0,但是如果长度设置为234.0,则文本将仅停止换行。

此代码演示了我上面所说的内容,并在计算的字形宽度右侧显示了一条垂直线。

- (void)drawRect:(NSRect)rect {
    NSRect bounds = [self bounds];

    [[NSColor whiteColor] drawSwatchInRect: bounds];
    [[NSColor blackColor] setStroke];
    [[NSBezierPath bezierPathWithRect: bounds] stroke];

    NSMutableParagraphStyle *thisParagraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
    [thisParagraphStyle setLineBreakMode: NSLineBreakByCharWrapping];
    [thisParagraphStyle setAlignment: NSLeftTextAlignment];

    NSFont *fontUsed = [NSFont fontWithName: @"Monaco" size: 12];

    NSDictionary *glyphAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                     fontUsed, NSFontAttributeName,
                                     thisParagraphStyle, NSParagraphStyleAttributeName,
                                     [NSColor blackColor], NSForegroundColorAttributeName,
                                     NULL];

    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:@"00112233445566778899001122334455\n00112233445566778899001122334455\n00112233445566778899001122334455\n00112233445566778899001122334455\n"];

    [textStorage setAttributes: glyphAttributes range:  NSMakeRange(0, [textStorage length])];

    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];

    NSSize textContainerSize;
    textContainerSize.width = [@"00112233445566778899001122334455" sizeWithAttributes: glyphAttributes].width;
    textContainerSize.height = bounds.size.height;

    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize: textContainerSize];
    [layoutManager addTextContainer:textContainer];

    [textContainer release];
    [textStorage addLayoutManager:layoutManager];
    [layoutManager release];
    NSRange glyphRange = [layoutManager glyphRangeForTextContainer: textContainer];

    [layoutManager drawGlyphsForGlyphRange: glyphRange atPoint: NSMakePoint(0.0 , 0.0)];
    [textStorage release];
    [thisParagraphStyle release];

    // Indicate right text boundary from computed width
    NSBezierPath *rightTextBoundary = [NSBezierPath bezierPath];
    [rightTextBoundary moveToPoint: NSMakePoint(textContainerSize.width, 0.0)];
    [rightTextBoundary lineToPoint: NSMakePoint(textContainerSize.width, bounds.size.height-1)];
    [rightTextBoundary stroke];

    NSLog(@"View width: %f", bounds.size.width);
    NSLog(@"Calculated width1: %f", textContainerSize.width);
    NSLog(@"Calculated width2: %f\n\n", [@"00112233445566778899001122334455" boundingRectWithSize: NSMakeSize(FLT_MAX, FLT_MAX)
                                                                         options: NSStringDrawingUsesDeviceMetrics
                                                                      attributes: glyphAttributes].size.width);
}

- (BOOL) isFlipped {
    return YES;
}

2 个答案:

答案 0 :(得分:1)

您是否考虑过文本容器的-lineFragmentPadding

答案 1 :(得分:1)

您是否看过NSString和NSAttributedString NS(Attributed)String+Geometrics这个类别?

如果它不是您正在寻找的东西,您可能会看到他们正在做的一些事情来计算尺寸。

相关问题