Рисование текста с основной графикой

Мне нужно нарисовать центрированный текст в CGContext.

Я начал с подхода какао. Я создал NSCell с текстом и попытался нарисовать его так:

NSGraphicsContext* newCtx = [NSGraphicsContext
     graphicsContextWithGraphicsPort:bitmapContext flipped:true];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:newCtx];
[pCell setFont:font];
[pCell drawWithFrame:rect inView:nil];
[NSGraphicsContext restoreGraphicsState];

Но в CGBitmapContext, похоже, не отображается текст. Возможно, потому что мне нужно передать nil для параметра inView :.

Поэтому я попытался переключить рендеринг текста на Core Graphics:

Кажется, что самый простой способ - использовать CGContextSelectFont для выбора шрифта, используя его имя postscript и размер точки, но CGContextShowTextAtPoint принимает только символы, отличные от Unicode, и нет очевидного способа уместить текст в прямоугольник: или вычислить пределы строки текста, чтобы вручную расположить прямоугольник.

Затем можно создать CGFont и установить cia CGContextSetFont. Для рисования этого текста требуется CGContextShowGlyphsAtPoint, но опять же в CGContext, похоже, отсутствуют функции для вычисления ограничивающего прямоугольника сгенерированного текста или для переноса текста в прямоугольник. Плюс неочевидно, как преобразовать строку в массив CGGlyphs.

Следующий вариант - попытаться использовать CoreText для визуализации строки. Но классы Core Text чрезвычайно сложны, и хотя есть образцы, которые показывают, как отображать текст заданным шрифтом в прямоугольнике, нет образцов, демонстрирующих, как вычислить ограничивающий прямоугольник строки CoreText.

So:

  • Учитывая CGFont и CGContext, как мне вычислить ограничивающий прямоугольник некоторого текста и как преобразовать текстовую строку в массив CGGlyphs?
  • Учитывая строку, CGContext и имя постскрипта и размер точки, какие объекты Core Text мне нужно создать для вычисления ограничивающего прямоугольника строки и / или рисования строки, заключенной в прямоугольник в CGContext.
  • Учитывая строку и NSFont - как мне отобразить строку в CGBitmapContext? Я уже знаю, как получить его экстенты.

person Chris Becke    schedule 08.12.2010    source источник
comment
могли бы вы нарисовать пример желаемого результата?   -  person hfossli    schedule 20.12.2010
comment
возможно, но желаемый результат очень прост - я хочу нарисовать строку с шрифтом (размер шрифта и точки) в прямоугольнике. Строка должна быть обернута, и я должен иметь возможность выбрать, будут ли строки выровнены по левому, среднему или правому краю, а также абзац, который будет выровнен по верхнему, центру или нижнему краю.   -  person Chris Becke    schedule 21.12.2010


Ответы (3)


Я бы продолжил ваш подход, но вместо этого использовал NSAttributedString.

NSGraphicsContext* newCtx = [NSGraphicsContext graphicsContextWithGraphicsPort:bitmapContext flipped:true];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:newCtx];
NSAttributedString *string = /* make a string with all of the desired attributes */;
[string drawInRect:locationToDraw];
[NSGraphicsContext restoreGraphicsState];
person Jon Hess    schedule 09.12.2010

Наконец-то мне удалось найти ответы после 4 дней поисков. Я действительно хочу, чтобы Apple делала лучшую документацию. Итак, мы идем

Я предполагаю, что у вас уже есть CGFontRef. Если не дайте мне знать, я расскажу вам, как загрузить ttf из пакета ресурсов в CgFontRef.

Ниже приведен фрагмент кода для вычисления границ любой строки с любым CGFontref.

        int charCount = [string length];
        CGGlyph glyphs[charCount];
        CGRect rects[charCount];

        CTFontGetGlyphsForCharacters(theCTFont, (const unichar*)[string cStringUsingEncoding:NSUnicodeStringEncoding], glyphs, charCount);
        CTFontGetBoundingRectsForGlyphs(theCTFont, kCTFontDefaultOrientation, glyphs, rects, charCount);

        int totalwidth = 0, maxheight = 0;
        for (int i=0; i < charCount; i++)
        {
            totalwidth += rects[i].size.width;
            maxheight = maxheight < rects[i].size.height ? rects[i].size.height : maxheight;
        }

        dim = CGSizeMake(totalwidth, maxheight);

Повторно используйте ту же функцию CTFontGetGlyphsForCharacters, чтобы получить глифы. Чтобы получить CTFontRef из CGFontRef, используйте функцию CTFontCreateWithGraphicsFont ()

Также помните, что NSFont и CGFontRef являются бесплатными мостами, что означает, что они могут быть преобразованы друг в друга, и они будут работать без каких-либо дополнительных усилий.

person Community    schedule 10.02.2011

Версия Swift 5!

let targetSize: CGSize = // the space you have available for drawing the text
let origin: CGPoint = // where you want to position the top-left corner
let string: String = // your string
let font: UIFont = // your font

let attrs: [NSAttributedString.Key:Any] = [.font: font]
let boundingRect = string.boundingRect(with: targetSize, options: [.usesLineFragmentOrigin], attributes: attrs, context: nil)
let textRect = CGRect(origin: origin, size: boundingRect.size)
text.draw(with: textRect, options: [.usesLineFragmentOrigin], attributes: attrs, context: nil)
person Robin Stewart    schedule 14.08.2019