Проблемы производительности CALayer CGPatternRef - PullRequest
0 голосов
/ 06 декабря 2011

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

Кажется довольно очевидным, что я мог бы оптимизировать, переместив распределение моих CGColorRef и CGPatternRef вне вызова drawLayer: inContext:, но я не уверен, как это сделать, поскольку оба полагаются на наличие CGContextRef.

Насколько я понимаю, контекст рисования CALayer фактически принадлежит его родительскому NSView и передается только во время рисования. Если это так, как лучше оптимизировать следующий код?

void drawCheckerboardPattern(void *info, CGContextRef context)
{
    CGColorRef alternateColor = CGColorCreateGenericRGB(1.0, 1.0, 1.0, 0.25);
    CGContextSetFillColorWithColor(context, alternateColor);

    CGContextAddRect(context, CGRectMake(0.0f, 0.0f, kCheckerboardSize, kCheckerboardSize));
    CGContextFillPath(context);

    CGContextAddRect(context, CGRectMake(kCheckerboardSize, kCheckerboardSize, kCheckerboardSize, kCheckerboardSize));
    CGContextFillPath(context);

    CGColorRelease(alternateColor);
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    CGFloat red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f;
    NSColor *originalBackgroundColor = [self.document.backgroundColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
    [originalBackgroundColor getRed:&red green:&green blue:&blue alpha:&alpha];

    CGColorRef bgColor = CGColorCreateGenericRGB(red, green, blue, alpha);
    CGContextSetFillColorWithColor(context, bgColor);
    CGContextFillRect(context, layer.bounds);

    // Should we draw a checkerboard pattern?
    if([self.document.drawCheckerboard boolValue])
    {
        static const CGPatternCallbacks callbacks = { 0, &drawCheckerboardPattern, NULL };

        CGContextSaveGState(context);
        CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
        CGContextSetFillColorSpace(context, patternSpace);
        CGColorSpaceRelease(patternSpace);

        CGPatternRef pattern = CGPatternCreate(NULL,
                                               CGRectMake(0.0f, 0.0f, kCheckerboardSize*2, kCheckerboardSize*2),
                                               CGAffineTransformIdentity,
                                               kCheckerboardSize*2,
                                               kCheckerboardSize*2,
                                               kCGPatternTilingConstantSpacing,
                                               true,
                                               &callbacks);
        alpha = 1.0f;
        CGContextSetFillPattern(context, pattern, &alpha);
        CGPatternRelease(pattern);
        CGContextFillRect(context, layer.bounds);
        CGContextRestoreGState(context);
    }

    CGColorRelease(bgColor);
}

1 Ответ

0 голосов
/ 06 декабря 2011

Вы можете создать шаблон вне вашего drawLayer:inContext: просто отлично, ему не нужен контекст.Так что просто создайте CGPatternRef переменную экземпляра и создайте шаблон.Это уже должно ускорить рендеринг, так как создание шаблона стоит дорого.Фактически, я бы создал всех CG* экземпляров, которым не нужен контекст вне вашего drawLayer:inContext: метода, так что все до CGColorCreateGenericRGB, а также CGColorSpaceCreatePattern.

...