Мы пытаемся получить предлагаемый размер кадра с помощью Core Text API CTFramesetterSuggestFrameSizeWithConstraints.
Пусть E = \ uFFFC; W = \ u200B; S = \ u00A0
CTFrameSetter создается со следующей строкой с атрибутами:
WSESWWSESW
Символам S и E присваиваются CTRunDelegates, которые имеют CTRunDelegateGetWidthCallback, которые возвращают 0 и говорят 100 соответственно.
Когда выполняется следующий код:
auto frameOptions = @{ (id)kCTFrameProgressionAttributeName: @(kCTFrameProgressionTopToBottom)) };
auto constraintSize = CGSizeMake(200, CGFLOAT_MAX);
CFRange fitRange = CFRangeMake(0, 0);
auto pathSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter_.get(), CFRangeMake(0, 0),(CFDictionaryRef)frameOptions, constraintSize, &fitRange);
Значение pathSize, возвращаемое API, равно 100, и мы получаем две отдельные строки
Затем мы создаем CTFrameRef, используя следующий фрагмент кода:
auto rect = CGRectMake(0, 0, 200, pathSize.height);
auto path = CGPathCreateWithRect(rect, nil));
auto frame = CTFramesetterCreateFrame(framesetter_.get(),
CFRangeMake(0, 0), path, (CFDictionaryRef)frameOptions));
Вопрос:
Почему CTFramesetterSuggestFrameSizeWithConstraints возвращает pathSize, который имеет ширину 100, когда очевидно, что ширина ограничения (200) должна быть достаточной для размещения всего текста в одной строке.
Как CoreText решает, какие символы / символы из строки с атрибутами должны быть объединены за один прогон? В приведенном выше примере мы получаем следующие две строки:
Строка 1: W S E SWW (4 CTTextRun)
Строка 2: S E SW (3 CTTextRun)
Может ли кто-нибудь помочь мне с ответами на эти два вопроса, связанных с вышеупомянутым сценарием. Заранее спасибо!
Изменить 1:
Добавление контекста к проблеме и нашему текущему подходу: Ссылка на изображение
Пожалуйста, обратитесь к изображению выше для ссылки на Parent, Child1, Child2.
Родитель представляет прямоугольник / прямоугольник, для которого мы хотим разметить и вычислить размеры. Мы хотим поместить текст в поле Родитель. Child1, Child2 представлены в нашем тексте символами «E».
- Сначала мы пытаемся вычислить размер родительского блока.
- Мы используем вычисленный размер родительского блока в качестве ограничений для
CTFramesetterSuggestFrameSizeWithConstraints, а затем используем его возвращаемое значение для создания CTFrame.
Вычисление размера. Вычисление размера родительского блока зависит от нескольких факторов - может быть заданный размер в качестве внешнего параметра, или он может быть получен из его контейнерного блока, или может быть равен размеру (зафиксирован на некоторые min, max) достаточно, чтобы уместить его текстовое содержимое. Таким образом, он не всегда неограничен (одна строка) или, иногда, даже не зависит от текстового содержимого.
Рассмотрим случай, когда вычисление зависит от текстового содержимого:
Итак, мы вычисляем ширину текста без каких-либо ограничений, используя:
CTFramesetterSuggestFrameSizeWithConstraints(framesetter_.get(), CFRangeMake(0, 0),
(CFDictionaryRef)frameOptions, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX), &fitRange);
Это возвращает значение 100 (child1) + 100 (child2) = ровно 200 пунктов. Допустим, у нас достаточно места, и 200 пунктов - это то, что установлено в качестве размера родительского блока.
Макет текста. На данный момент у нас есть только рассчитанный размер родительского поля и нет информации о том, как он был рассчитан.
Если теперь мы используем ограничения 200 точек с CTFramesetterSuggestFrameSizeWithConstraints, он возвращает 100 точек и разбивает текст на две строки.
Вот где у нас есть проблема - неограниченный размер текста при использовании для создания CTFrame дает неожиданный разрыв строки.
greatestFiniteMagnitude
, или просто используйте 10 000). Если вы можете увеличить ограничения, они не были настоящими ограничениями. - person Rob Napier   schedule 29.01.2021