CTLine или NSAttributedString - получить границы изображения без графического контекста? - PullRequest
0 голосов
/ 08 октября 2011

Возможно ли это? По сути, у меня есть несколько объектов NSAttributedString и соответствующих объектов CTLine. Я хочу получить границы изображения до этапа drawRect. Так что на данный момент нечего привлекать. Затем я буду использовать эти границы изображения, чтобы точно решить, что мне нужно создать для рисования.

РЕДАКТИРОВАТЬ: другое измерение размера, вероятно, будет работать просто отлично. Но вызов обманчиво названной функции CTLineGetTypographicBounds возвращает только ширину. Если я передаю адреса всплывающих и спускающихся плаваний, они возвращаются как ноль.

РЕДАКТИРОВАТЬ: данный ответ прекрасно работает в MacOS. Кто-нибудь может сделать это в iOS?

Ответы [ 4 ]

2 голосов
/ 05 сентября 2013

Если вы разрабатываете для iOS6 +.Вы можете использовать следующий метод:

CTLineRef line;
// Create the line...

CGRect bounds = CTLineGetBoundsWithOptions(line, kCTLineBoundsUseGlyphPathBounds);
// use bounds...

Это дает те же границы, что и CTLineGetImageBounds(), при условии, что в вашем контексте не применены преобразования, но контекст не требуется.Для iOS 5 и ниже вам нужно будет использовать метод, описанный Иван.

CTLineGetTypographicBounds() дает мне ширину, отличную от этой функции или границ изображения.Я не уверен почему.И возвращаются всплытие и спуск с использованием шрифта, а не символов, отображаемых в CTLineRef.

2 голосов
/ 24 января 2012

Границы, возвращаемые CTLineGetTypographicBounds(), не совпадают с границами изображения. Как следует из названия (и ответа Ивана), для шрифта определено восхождение и т. Д., Которое не будет меняться в зависимости от строки. Например, вы могли бы использовать его, если хотите найти правильную высоту строки, если у вас есть многострочный текст, поскольку высота строки обычно не должна зависеть от того, какие именно символы вы используете.

CTLineGetImageBounds(), с другой стороны, возвращает границы, которые точно соответствуют изображению. Например, если вы хотите нарисовать рамку вокруг одной линии, это то, что вам нужно.

CTLineGetImageBounds() нужен контекст, потому что могут быть преобразования текста и тому подобное. Если вы не хотите беспокоиться об этом, просто используйте фиктивный контекст. Например:

CTLineRef line;

// create the line...

UIGraphicsBeginImageContext(CGSizeMake(1, 1));
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextPosition(context, 0, 0);
CGRect bounds = CTLineGetImageBounds(line, context);
UIGraphicsEndImageContext();

// use bounds...
2 голосов
/ 25 ноября 2011

Да, вы можете, но не так просто.

Обычно вы должны использовать CTLineGetTypographicBounds () , который, для меня, возвращает восхождение , спуск и впереди , но немного запутано - ' подъем ' равняется общей высоте (то есть, что должно быть подъемом и спуском) и ' спуском 'всегда максимальный спуск шрифта - независимо от того, есть у вас нисходящие символы или нет.

Другой способ - извлечь CTRun (s) из строки (CTLineGetGlyphRuns ), затем получите массив глифов ( CTRunGetGlyphs или CTRunGetGlyphsPtr ), а затем с помощью CTFontGetBoundingRectsForGlyphs и Создайте *1027* * *вам нужно.

РЕДАКТИРОВАТЬ: Я только что нашел этот метод: " - (NSRect) boundingRectWithSize: (NSSize) параметры размера: (NSStringDrawingOptions) options " из NSAttributedString который, кажется, делает точно что нужнод.

Надеюсь, это полезно ...

0 голосов
/ 17 сентября 2012

Другой метод - преобразовать строку в глифы, используя CTFontGetGlyphsForCharacters(), а затем вызвать CTFontGetBoundingRectsForGlyphs() с массивом глифов, полученным из первой функции.Последняя функция возвращает «общий ограничивающий прямоугольник для запуска глифа», поэтому не беспокойтесь о необходимости обработки отдельных ограничивающих строк.При успешном использовании обеих этих функций в iOS.

Если вы это сделаете, помните, что сопоставление между глифами и символами не всегда один к одному, особенно когда строка содержит неанглийские символы.

...