Используйте CATextLayer с CGContext - PullRequest
1 голос
/ 23 января 2012

Мне нужно нарисовать текст в CGContext и хочу использовать CATextLayer для установки текста.Может кто-нибудь дать мне несколько шагов относительно того, как это будет сделано.Я написал некоторый код для него, но не знаю его правильность (так как я новичок в iPhone Development).

Некоторые основные вопросы: 1. Как определить положение и размер текста дляустановка фрейма CATextLayer 2. Текст каким-то образом получается инвертированным, что я исправил с помощью CGAffineTransform, но это хакерское исправление, и я хочу знать реальную причину, по которой текст выходит инвертированным.3. Мне также нужно установить ширину и цвет границы текста, для которых я использую NSAttributedString, но настройка размера текста (увеличение или уменьшение) не отражается на экране.

РЕДАКТИРОВАТЬ 1:

Я обновил код в соответствии с вашими рекомендациями, но размер текста не изменился даже после использования CTFontRef.Кроме того, на iPhone текст немного обрезается сверху.Любая идея, что устанавливается неправильно?Когда я проверил значения, полученные из getTypographicBounds, все они равны 0 (origin.x, origin.y, width и height).

Метод getTypographicBounds:

width = CTLineGetTypographicBounds(m_line, &ascent, &descent, &leading);

// Return text bounds
return CGRectMake(0, 0, width, ascent + descent);

Измененный код:

CATextLayer*    text      = [[CATextLayer alloc] init];
CGColorSpaceRef rgbColor  = CGColorSpaceCreateDeviceRGB();
CGColorRef rgb            = CGColorCreate(rgbColor, m_fill_color);
text.foregroundColor      = rgb;
text.frame                = CGRectMake([self getTypographicBounds].origin.x, [self getTypographicBounds].origin.y, [self getTypographicBounds].size.width + 2*m_padding, [self getTypographicBounds].size.height + 2*m_padding);
text.wrapped              = YES;

    NSMutableDictionary *stringAttributes = [NSMutableDictionary dictionary];

    CTFontRef aCFFont = CTFontCreateWithName ((CFStringRef)m_font_name, 30.0, NULL);

    // Set a negative width so we get both stroke and fill to show
    [stringAttributes setObject: (NSObject*)aCFFont forKey: (id)kCTFontNameAttribute];
    [stringAttributes setObject: [NSNumber numberWithFloat: -3 ] forKey: (id)kCTStrokeWidthAttributeName];
    [stringAttributes setObject: [UIColor whiteColor] forKey: (id)kCTStrokeColorAttributeName];

    NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:m_text
                                                                       attributes:stringAttributes];

    text.string = (NSString*)stringToDraw;
    [text drawInContext:ctx];

РЕДАКТИРОВАТЬ 2: пример вики использует CTLine, я использую CATextLayer.Reason :: CATextLayer позволяет мне изменять текст во время выполнения, чтобы показать китайский, японский, хинди, русский и все языки с различными сценариями.Кроме того, CATextLayer выглядит более четко, чем CoreText.

Проблема, с которой я сейчас сталкиваюсь, заключается в том, что текст, отображаемый строкой [text drawInContext: ctx], усекается сверху.Я проверил рамку и размер шрифта текста.Размер шрифта составляет 16 пикселей, а высота кадра - 17,768, поэтому я не знаю, почему он усекается.

// Ensure CTLine is up-to-date
if (m_is_dirty)
    [self recomputeLine];

// Get text metrics
CGFloat width;
CGFloat ascent;
CGFloat descent;
CGFloat leading;

width = CTLineGetTypographicBounds(m_line, &ascent, &descent, &leading);

// Position text so that top of text aligns with top of layer
CGContextSetTextMatrix(ctx, CGAffineTransformIdentity );

// Setup text drawing style
CGContextSetRGBFillColor   (ctx, m_fill_color  [0], m_fill_color  [1], m_fill_color  [2], 1.0);
CGContextSetRGBStrokeColor (ctx, m_stroke_color[0], m_stroke_color[1], m_stroke_color[2], 1.0);
CGContextSetFont           (ctx, m_font        );
CGContextSetFontSize       (ctx, m_font_size   );
CGContextSetLineWidth      (ctx, m_stroke_width);

CATextLayer*    text      = [[CATextLayer alloc] init];
CGColorSpaceRef rgbColor  = CGColorSpaceCreateDeviceRGB();
CGColorRef rgb            = CGColorCreate(rgbColor, m_fill_color);
text.foregroundColor      = rgb;
text.fontSize = m_font_size;
text.font = m_font;
text.frame                = CGRectMake([self getTypographicBounds].origin.x, [self getTypographicBounds].origin.y, [self getTypographicBounds].size.width, [self getTypographicBounds].size.height);
text.wrapped              = YES;

NSMutableDictionary *stringAttributes = [NSMutableDictionary dictionary];


// Set a negative width so we get both stroke and fill to show
[stringAttributes setObject: [UIFont fontWithName:m_font_name size:m_font_size] forKey: (id)kCTFontNameAttribute];
[stringAttributes setObject: [NSNumber numberWithFloat: -3 ] forKey: (id)kCTStrokeWidthAttributeName];
[stringAttributes setObject: [UIColor whiteColor] forKey: (id)kCTStrokeColorAttributeName];

NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:m_text
                                                                       attributes:stringAttributes];

text.string = (NSString*)stringToDraw;        
[text drawInContext:ctx];

Заранее спасибо

Ник

1 Ответ

1 голос
/ 23 января 2012

Это из-за перевернутого координатного пространства, используемого для CGContexts. Для полного объяснения (с диаграммами) см. здесь .

EDIT: Чтобы контролировать позицию, переведите ваш контекст перед рисованием текста:

CGContextTranslateCTM(context, x, y);

РЕДАКТИРОВАТЬ 2:

Похоже, вам нужно использовать CTFontRef, а не UIFont. Для примера, см. здесь (см. Сообщение от Gordon Apple, среда, 23 июня, 10:40:23 2010 г.).

РЕДАКТИРОВАТЬ 3:

Если вам не требуется специально использовать NSAttributedString, я бы рекомендовал использовать гораздо более простой метод NSString drawInRect: withFont: lineBreakMode: alignment: метод. Он создает CATextLayer для вас, но его гораздо проще использовать:

    UIFont *font = [UIFont fontWithName:m_font_name size:30.f];
    [m_text drawInRect:text.frame  withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];

РЕДАКТИРОВАТЬ 4:

Попробуйте установить словарь так:

    CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)fontName, pointSize,NULL);
    CGColorRef color = textColor.CGColor;

    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (__bridge id)ctFont, (id)kCTFontAttributeName,
                                    color, (id)kCTForegroundColorAttributeName,nil];
...