Вопрос по objective-c, ios – Предоставление Framesetter правильной регулировки межстрочного интервала

3

В нескольких сообщениях отмечались трудности с получением точной высоты из CTFramesetterSuggestFrameSizeWithConstraints, и здесь,(пост фреймсеттера)@Chris DeSalvo дает то, что выглядит как окончательное исправление: добавьте настройку стиля абзаца с правильной настройкой межстрочного интервала.

DeSalvo получает свою & # x201C; ведущую & # x201D; удалив UIFont's ascender и descender из его lineHeight. Интересно, как это будет сравниваться сCTFontGetLeading.

Я работал со шрифтами, созданными так:

CTFontRef fontr = CTFontCreateWithName((CFStringRef)@"Helvetica Neue", 16.0f, NULL);
UIFont *font = [UIFont fontWithName:@"Helvetica Neue" size:16.0f];

Значения были совсем другие:

0.448 CTFontGetLeading 2.360 DeSalvo’s formula: UIFont lineHeight - ascender + descender

Вот некоторые другие значения UIFont:

21.000 UIFont’s lineHeight 15.232 UIFont’s ascender (Y coord from baseline) -3.408 UIFont’s descender (Y coord from baseline) 08.368 UIFont’s xHeight

А вот значения CTFont, о которых спрашивал Кен Томасес:

11.568001 CTFontGetCapHeight 08.368 CTFontGetXHeight -15.216001, -7.696001, 38.352001, 24.928001 CTFontGetBoundingBox 15.232 CTFontGetAscent 03.408 CTFontGetDescent (class ref says "scaled font-descent metric scaled according to the point size and matrix of the font reference" -- which apparently means that it is the absolute value of the Y coordinate from the baseline?)

Отмечу, что ранее у UIFont было свойство специально для & # x201C; lead, & # x201D; но это устарело, и мы рекомендуем использоватьlineHeight вместо. Таким образом, UIFont считает ведущим21 и CTFontRef.448 для того же шрифта? Что-то не так.

Три вопроса:

Is “leading” really what is meant by kCTParagraphStyleSpecifierLineSpacingAdjustment? If so, which method/formula should I use to get it? If not, what should I use for the line spacing adjustment?
Отличная идея. Я добавил эти значения CTFontGet к вопросу. Я не вижу комбо, которые бы дали 0,448. И мне интересно, как мы могли бы думать с точки зрения высоты линии при рассмотренииinterмежстрочный интервал, особенно когда высота строки определяется просто как «высота текстовых строк»? Wienke
Вы пробовали установкуkCTParagraphStyleSpecifierMinimumLineHeight вместо регулировки пространства строки? По крайней мере, у вас есть определенная ценность для этого. Ken Thomases
Ну, LineSpacingAdjustment также не даст вам точную высоту линии. Как следует из его названия, это корректировка того, что вычислитель кадров вычисляет из шрифта. Если вы хотите иметь постоянную высоту строки, установите MinimumLineHeight и MaximumLineHeight. Я не знаком с архитектурой представления текста в iOS, но я был бы удивлен, если бы она не предоставила средства для прокрутки положения или диапазона символа в представлении. Например, NSTextView Mac OS X имеет-scrollRangeToVisible: наследуется от NSText. Ken Thomases
Я только сейчас собираю реализацию. Ранее я использовал метод NSString UIKitsizeWithFont:, что сложно из-за игнорирования разрывов строк, и мне посоветовали перейти на метод фрейм-сеттера. я хочуexact высота строки, а не максимальная или минимальная, чтобы я мог рассчитать, какой будет высота contentSize для textLayer и UIScrollView, и чтобы я мог прокручивать новые добавленные строки. Wienke
Я не думаю, что было предложено использоватьlineHeight в качестве замены для ведущих. Я думаю, что предложение заключалось в том, чтобы перестать заботиться о лидерстве и вместо этого думать о высоте линии. Тем не менее, я не могу примирить разницу между CTFontGetLeading и формулой. Что дают другие функции CTFontGet ... (подъем, высота ограничительной рамки, спуск, высота крышки, высота х)? Ken Thomases

Ваш Ответ

2   ответа
1

и вот код, который работал в реальном проекте:

// When you create an attributed string the default paragraph style has a leading 
// of 0.0. Create a paragraph style that will set the line adjustment equal to
// the leading value of the font. This logic will ensure that the measured
// height for a given paragraph of attributed text will be accurate wrt the font.

- (void) applyParagraphAttributes:(CFMutableAttributedStringRef)mAttributedString
{
  CGFloat leading = CTFontGetLeading(self.plainTextFont);

  CTParagraphStyleSetting paragraphSettings[1] = {
    kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof (CGFloat), &leading
  };

  CTParagraphStyleRef  paragraphStyle = CTParagraphStyleCreate(paragraphSettings, 1);

  CFRange textRange = CFRangeMake(0, [self length]);

  CFStringRef keys[] = { kCTParagraphStyleAttributeName };
  CFTypeRef values[] = { paragraphStyle };

  CFDictionaryRef attrValues = CFDictionaryCreate(kCFAllocatorDefault,
                                                  (const void**)&keys,
                                                  (const void**)&values,
                                                  sizeof(keys) / sizeof(keys[0]),
                                                  &kCFTypeDictionaryKeyCallBacks,
                                                  &kCFTypeDictionaryValueCallBacks);

  BOOL clearOtherAttributes = FALSE;
  CFAttributedStringSetAttributes(mAttributedString, textRange, attrValues, (Boolean)clearOtherAttributes);
  CFRelease(attrValues);

  CFRelease(paragraphStyle);

  self.stringRange = textRange;

  return;
}
0

Yes, “leading” really what is meant by kCTParagraphStyleSpecifierLineSpacingAdjustment. Or at any rate, it works as expected. Use CTFontGetLeading(fontRef) to get the font's normal leading, or plug in whatever value (as a CGFloat) you choose. N/A.

Работа с ответами 1 и 2: Указание начального значения в атрибуте paraStyle вашей атрибутивной строки позволит Core-Text framesetter рассчитать его высотуexactly.

Есть две оговорки:

If you try to calculate heights incrementally, one string at a time, each string containing an initial line break, framesetter will consider that line break to represent an entire line, not just the leading. If you want the height of the concatenated strings, you have to feed that concatenation to the framesetter. Of course, you could keep track of the incremental height differences, but there's no way to avoid having framesetter recalculate the earlier string dimensions. CATextLayer ignores spacing adjustments (and other attributes). If framing per exact string height is an issue, you must draw direct to a CALayer.

И есть одна загадка: что происходит с устаревшим лидерством UIFont? Leading и lineHeight - это две разные вещи.

Похожие вопросы