Ошибка в CTFrameGetLineOrigins? - PullRequest
0 голосов
/ 21 марта 2012

Я использую следующий код из SimpleTextInput примера Apple, чтобы определить рамку для курсора.Я использую 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];
}

Ответы [ 3 ]

2 голосов
/ 04 октября 2012
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)));
}
1 голос
/ 21 марта 2012

Ваш диапазон длиной 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}}
...
0 голосов
/ 05 июня 2012

Как ни странно, я решил эту проблему, заменив:

CGPathAddRect(textFrameMutablePath, NULL, self.bounds);

с

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

Понятия не имею почему, но это работает.

...