【问题标题】:Bug in CTFrameGetLineOrigins?CTFrameGetLineOrigins 中的错误?
【发布时间】:2012-03-21 17:17:59
【问题描述】:

我使用 Apple 的 SimpleTextInput 示例中的以下代码来确定光标的框架。我正在使用CTFrameGetLineOrigins,我注意到它返回的 y 值不正确(无论在哪一行,它都显示 .336)。我的应用程序与SimpleTextInput 略有不同,因为我将文本垂直居中,因此文本框架不会直接从原点开始。但是,为什么它给我每一行的这个价值?这是一个错误吗?

for (int i = 0; i < [lines count]; i++) 
{
    CTLineRef line = (CTLineRef) [lines objectAtIndex:i];
    CFRange range = CTLineGetStringRange(line);
    NSInteger localIndex = index - range.location;

    if (localIndex >= 0 && localIndex <= range.length) 
    {
        CGPoint origin;
        CGFloat ascent, descent;
        CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
        CTFrameGetLineOrigins(self.textFrame, CFRangeMake(i, 0), &origin);
        CGFloat xPos = origin.x + CTLineGetOffsetForStringIndex(line, index, NULL);
        return CGRectMake(xPos, origin.y - descent, 3, ascent + descent);
    }
}

- (void) drawRect:(CGRect)rect
{
    CTFramesetterRef textFramesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.text);
    CGMutablePathRef textFrameMutablePath = CGPathCreateMutable();
    CGPathAddRect(textFrameMutablePath, NULL, self.bounds);
    self.textFrame = CTFramesetterCreateFrame(textFramesetter, CFRangeMake(0, 0), textFrameMutablePath, NULL);

    CGFloat textFrameHeight = [self calculateHeightForTextFrame];
    CGRect textFrameRect = CGRectMake(0, (self.bounds.size.height / 2) - (textFrameHeight / 2), self.bounds.size.width, textFrameHeight);

    CGPathRelease(textFrameMutablePath);
    textFrameMutablePath = NULL;

    CFRelease(self.textFrame);
    self.textFrame = NULL;

    textFrameMutablePath = CGPathCreateMutable();
    CGPathAddRect(textFrameMutablePath, NULL, textFrameRect);
    self.textFrame = CTFramesetterCreateFrame(textFramesetter, CFRangeMake(0, 0), textFrameMutablePath, NULL);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CTFrameDraw(self.textFrame, context); 

    CGPathRelease(textFrameMutablePath);
    CFRelease(textFramesetter);

    [self cursorPositionChanged];
}

【问题讨论】:

    标签: iphone ios cocoa-touch core-graphics core-text


    【解决方案1】:
    Take out CTFrameGetLineOrigins() out of loop to get all line origins like :
    
    NSArray *lines = (__bridge id)CTFrameGetLines(frame);
    CGPoint origins[lines.count];
    CTFrameGetLineOrigins(frame, CFRangeMake(0, lines.count), origins); //this will fill all line origins in origins[] buffer.
    
    for (int i = 0; i < [lines count]; i++)
    {
        CTLineRef line = (__bridge CTLineRef) [lines objectAtIndex:i];
        CFRange range = CTLineGetStringRange(line);
    
        // CGPoint origin; // moved out of loop
        CGFloat ascent, descent;
        CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
        // CTFrameGetLineOrigins(frame, CFRangeMake(i, 1), &origin); // moved to out of loop
        CGFloat xPos = origins[i].x; //  + CTLineGetOffsetForStringIndex(line, index, NULL);
        NSLog(@"%@", NSStringFromCGRect(CGRectMake(xPos + origins[i].x, origins[i].y - descent, 3, ascent + descent)));
    }
    

    【讨论】:

      【解决方案2】:

      您的范围是 0 个元素长:

      CFRangeMake(i, 0)
      

      你的意思是让它长 1 个元素:

      CFRangeMake(i, 1)
      

      编辑:

      我刚刚尝试了以下代码,并且为每一行获取不同的来源没有问题。我取出了你的“索引”代码,因为我不知道应该设置什么索引,我想证明我可以得到所有的行来源(我可以)。

      CTFramesetterRef
            framesetter = CTFramesetterCreateWithAttributedString(attrString);
      
      
        CFArrayRef paths = [self copyPaths];
        CFIndex pathCount = CFArrayGetCount(paths);
        CFIndex charIndex = 0;
        for (CFIndex pathIndex = 0; pathIndex < pathCount; ++pathIndex) {
          CGPathRef path = CFArrayGetValueAtIndex(paths, pathIndex);
      
          CTFrameRef
              frame = CTFramesetterCreateFrame(framesetter,
                                               CFRangeMake(charIndex, 0),
                                               path,
              NULL);
      
          NSArray *lines = (__bridge id)CTFrameGetLines(frame);
          for (int i = 0; i < [lines count]; i++)
          {
            CTLineRef line = (__bridge CTLineRef) [lines objectAtIndex:i];
            CFRange range = CTLineGetStringRange(line);
      
            CGPoint origin;
            CGFloat ascent, descent;
            CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
            CTFrameGetLineOrigins(frame, CFRangeMake(i, 1), &origin);
            CGFloat xPos = origin.x; //  + CTLineGetOffsetForStringIndex(line, index, NULL);
            NSLog(@"%@", NSStringFromCGRect(CGRectMake(xPos, origin.y - descent, 3, ascent + descent)));
          }
      

      在我的情况下输出:

      2012-03-21 18:28:19.834 Columns[9370:f803] {{0, 929.24}, {3, 12}}
      2012-03-21 18:28:19.835 Columns[9370:f803] {{0, 914.24}, {3, 12}}
      2012-03-21 18:28:19.835 Columns[9370:f803] {{0, 899.24}, {3, 12}}
      2012-03-21 18:28:19.836 Columns[9370:f803] {{0, 884.24}, {3, 12}}
      2012-03-21 18:28:19.836 Columns[9370:f803] {{0, 869.24}, {3, 12}}
      2012-03-21 18:28:19.836 Columns[9370:f803] {{0, 854.24}, {3, 12}}
      2012-03-21 18:28:19.837 Columns[9370:f803] {{0, 839.24}, {3, 12}}
      2012-03-21 18:28:19.837 Columns[9370:f803] {{0, 824.24}, {3, 12}}
      2012-03-21 18:28:19.838 Columns[9370:f803] {{0, 809.24}, {3, 12}}
      2012-03-21 18:28:19.838 Columns[9370:f803] {{0, 794.24}, {3, 12}}
      2012-03-21 18:28:19.838 Columns[9370:f803] {{0, 779.24}, {3, 12}}
      2012-03-21 18:28:19.839 Columns[9370:f803] {{0, 764.24}, {3, 12}}
      ...
      

      【讨论】:

      • 谢谢我解决了这个问题,仍然有同样的问题。猜猜这是一个错误,我只需要使用其他方法来确定 y 原点。
      【解决方案3】:

      奇怪的是,我似乎已经通过替换解决了这个问题:

      CGPathAddRect(textFrameMutablePath, NULL, self.bounds);
      

      CGPathAddRect(textFrameMutablePath, NULL, CGRectInset(self.bounds, self.horizontalInset, self.verticalInset));
      

      不知道为什么,但它有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-18
        • 1970-01-01
        • 2018-04-24
        • 2012-05-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多