Печать CALayers

У меня есть NSView, который содержит много CALayers. Когда пользователь редактирует документ, эти CALayers анимируют все изменения. Я пытаюсь реализовать печать для своего приложения, но у меня возникают проблемы с правильной печатью этих CALayers.

Некоторые границы CALayers занимают весь NSView, и их не нужно размещать, потому что их положение никогда не меняется. Однако у меня также есть один CALayer, который содержит около 20 маленьких CALayer'ов. Эти CALayers анимируют изменения своего положения во время обычного редактирования. Однако при попытке распечатать NSView эти маленькие уровни клиентского доступа никогда не размещаются правильно. Мне интересно, есть ли что-то особенное, что я должен сделать, чтобы убедиться, что эти слои расположены правильно и позволяют правильно рисовать / печатать NSView.

Есть ли у кого-нибудь опыт печати NSView с поддержкой Core Animation? Любые предложения приветствуются.


person CJ.    schedule 05.05.2010    source источник


Ответы (2)


Чтобы обойти проблемы макета, а также тот факт, что использование -renderInContext: для рисования иерархии слоев не сохраняет векторные элементы, мы создали подкласс CALayer в Core Plot framework. Подкласс CPLayer переопределяет метод -drawInContext: по умолчанию для вызова нашего пользовательского метода -renderAsVectorInContext: (где мы делаем все наши отрисовки базовой графики для слоя). Чтобы создать контекст PDF (или аналогичный) для печати, мы затем вызываем настраиваемый метод со следующим кодом:

-(void)recursivelyRenderInContext:(CGContextRef)context
{
    // render self
    CGContextSaveGState(context);

    [self applyTransform:self.transform toContext:context];

    self.renderingRecursively = YES;
    if ( !self.masksToBounds ) {
        CGContextSaveGState(context);
    }
    [self renderAsVectorInContext:context];
    if ( !self.masksToBounds ) {
        CGContextRestoreGState(context);
    }
    self.renderingRecursively = NO;

    // render sublayers
    for ( CALayer *currentSublayer in self.sublayers ) {
        CGContextSaveGState(context);

        // Shift origin of context to match starting coordinate of sublayer
        CGPoint currentSublayerFrameOrigin = currentSublayer.frame.origin;
        CGRect currentSublayerBounds = currentSublayer.bounds;
        CGContextTranslateCTM(context,
                              currentSublayerFrameOrigin.x - currentSublayerBounds.origin.x, 
                              currentSublayerFrameOrigin.y - currentSublayerBounds.origin.y);
        [self applyTransform:self.sublayerTransform toContext:context];
        if ( [currentSublayer isKindOfClass:[CPLayer class]] ) {
            [(CPLayer *)currentSublayer recursivelyRenderInContext:context];
        } else {
            if ( self.masksToBounds ) {
                CGContextClipToRect(context, currentSublayer.bounds);
            }
            [currentSublayer drawInContext:context];
        }
        CGContextRestoreGState(context);
    }
    CGContextRestoreGState(context);
}

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

Еще одна вещь, на которую следует обратить внимание при попытке визуализации слоев, заключается в том, что состояние иерархии уровня представления может отличаться от состояния иерархии внутреннего слоя. У вас может быть анимация, примененная для перемещения ваших слоев, но свойства position слоев, возможно, не были изменены для соответствия. В этом случае вы должны убедиться, что вы либо анимируете сами свойства, чтобы значения всегда оставались синхронизированными, либо устанавливаете значения в вашем слое после завершения анимации.

person Brad Larson    schedule 07.05.2010

В последний раз я обнаружил, что правильно распечатать CALayers не удалось. В то время мне казалось, что Core Animation была разработана только для экрана, а не для печати (что, кажется, согласуется с тем фактом, что изначально она была разработана для iPhone).

Я бы хотел знать, что ошибаюсь.

person wbyoung    schedule 05.05.2010