2013-05-03 3 views
4

У меня есть некоторые проблемы с CATextLayer, которые могут быть из-за меня, но я не нашел никакой помощи по этой теме. Я на OS X (на iOS он должен быть таким же).CATextLayer получает растрированный слишком рано, и он размыт

Я создаю слои CATextLayer с коэффициентом масштабирования> 1, и то, что я получаю, является размытым текстом. Думаю, слой растеризован перед применением шкалы. Это ожидаемое поведение? Надеюсь, это не так, потому что это просто не имеет смысла ... CAShapeLayer растеризован после того, как применяется матрица преобразования, почему CATextLayer должен быть другим?

В случае, если я делаю что-то неправильно ... что это такое ??

CATextLayer *layer = [CATextLayer layer]; 
layer.string = @"I like what I am doing"; 
layer.font = (__bridge CFTypeRef)[NSFont systemFontOfSize:24]; 
layer.fontSize = 24; 
layer.anchorPoint = CGPointZero; 
layer.frame = CGRectMake(0, 0, 400, 100); 
layer.foregroundColor = [NSColor blackColor].CGColor; 
layer.transform = CATransform3DMakeScale(2., 2., 1.); 
layer.shouldRasterize = NO; 
[self.layer addSublayer:layer]; 

Решение, которое я использую в данный момент, заключается в том, чтобы установить свойство contentsSlale слоя в коэффициент масштабирования. Проблема заключается в том, что это решение не масштабируется: если масштабный коэффициент для любого из родительских слоев изменяется, то также необходимо обновить contentsScale. Я должен написать код, чтобы пересечь дерево слоев, чтобы обновить свойства contentsScale всех CATextLayers ... не совсем то, что я хотел бы сделать.

Другим решением, которое на самом деле не является решением, является преобразование текста в форму и использование CAShapeLayer. Но тогда я не вижу смысла иметь CATextLayers.

Пользовательский подкласс CALayer может помочь в решении этой проблемы?

EDIT: Даже CAGradientLayer может отображать его содержимое, например CAShapeLayer, после чего применяется его матрица преобразования. Может кто-нибудь объяснить, как это возможно?

EDIT 2: Я предполагаю, что пути и градиенты отображаются в виде списков отображения OpenGL, поэтому они растеризуются в реальном размере на экране самим OpenGL. Тексты растеризуются Core Animation, поэтому они являются растровыми изображениями для OpenGL.

Я думаю, что на данный момент я перейду с содержимым. Возможно, в будущем я буду конвертировать тексты в формы. Для того, чтобы получить лучшие результаты с небольшим количеством работы, это код, который я использую сейчас:

[CATransaction setDisableActions:YES]; 

CGFloat contentsScale = ceilf(scaleOfParentLayer); 
// _scalableTextLayer is a CATextLayer 
_scalableTextLayer.contentsScale = contentsScale; 
[_scalableTextLayer displayIfNeeded]; 

[CATransaction setDisableActions:NO]; 

ответ

1

Перепробовав все подходы, решение я использую в настоящее время является пользовательский подкласс CALayer. Я вообще не использую CATextLayer.

Я переопределить свойство contentsScale с помощью этого метода пользовательских инкубационного:

- (void)setContentsScale:(CGFloat)cs 
{ 
    CGFloat scale = MAX(ceilf(cs), 1.); // never less than 1, always integer 
    if (scale != self.contentsScale) { 
     [super setContentsScale:scale]; 
     [self setNeedsDisplay]; 
    } 
} 

Значения свойства всегда округляется до верхнего значения целого числа. Когда округленное значение изменяется, слой должен быть перерисован.

Метод отображения моего подкласса CALayer создает растровое изображение размера текста, умноженное на коэффициент contentsScale и коэффициент масштабирования экрана.

- (void)display 
{ 
    CGFloat scale = self.contentsScale * [MyUtils screenScale]; 

    CGFloat width = self.bounds.size.width * scale; 
    CGFloat height = self.bounds.size.height * scale; 

    CGContextRef bitmapContext = [MyUtils createBitmapContextWithSize:CGSizeMake(width, height)]; 

    CGContextScaleCTM(bitmapContext, scale, scale); 
    CGContextSetShouldSmoothFonts(bitmapContext, 0); 

    CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)(_text)); 

    CGContextSetTextPosition(bitmapContext, 0., self.bounds.size.height-_ascender); 
    CTLineDraw(line, bitmapContext); 
    CFRelease(line); 

    CGImageRef image = CGBitmapContextCreateImage(bitmapContext); 
    self.contents = (__bridge id)(image); 
    CGImageRelease(image); 

    CGContextRelease(bitmapContext); 
} 

При изменении коэффициента масштабирования корневого слоя моей иерархии, я петля на все текстовые слои и установить свойство contentsScale к тому же фактору. Метод отображения вызывается только в том случае, если округленное значение масштабного коэффициента изменяется (т. Е. Если предыдущее значение было 1,6, и теперь я устанавливаю 1,7, ничего не происходит, но если новое значение равно 2.1, тогда слой повторно отображается).

Стоимость с точки зрения скорости перерисовки немного. Мой тест заключается в постоянном изменении масштабного коэффициента иерархии 40 текстовых слоев на 3-м гене. IPAD. Он работает как масло.

0

CATextLayer отличается тем, что лежащий в основе CoreText оказывает глифы с указанным размером шрифта (догадка, основанная на экспериментах).

Вы можете добавить действие к родительскому слою, так как при изменении масштаба он изменит размер шрифта текстового слоя.

Размытость может также исходить из несогласованных пикселей. Это может произойти, если вы поместите текстовый слой в нецелевое положение или любое преобразование в иерархии суперслоев.

В качестве альтернативы вы можете создать подкласс CALayer, а затем нарисовать текст с использованием какао в drawInContext: смотри пример здесь: http://lists.apple.com/archives/Cocoa-dev/2009/Jan/msg02300.html http://people.omnigroup.com/bungi/TextDrawing-20090129.zip

+0

Hi mahal, спасибо, что ответили. Я не могу изменить размер шрифта при изменении масштаба родительского слоя: размер текста будет умножен на коэффициент масштабирования родителя и на больший размер шрифта без какой-либо выгоды. Я получаю больший, размытый текст. – mbt

+0

Это работало? Затем вы можете добавить несколько подробностей и пометить вопрос как ответ. –

0

Если вы хотите иметь точное поведение CAShapeLayer, то вам нужно будет конвертировать ваши строка в путь безье, и CAShapeLayer визуализирует ее. Это немного работа, но тогда у вас будет точное поведение, которое вы ищете. Альтернативный подход - это масштабирование fontSize. Это дает четкий текст каждый раз, но это может не соответствовать вашей конкретной ситуации.

+0

Привет "level", проблема в том, что мне нужно установить коэффициент масштабирования для родителя, поэтому я не могу изменить размер шрифта. – mbt

 Смежные вопросы

  • Нет связанных вопросов^_^