Печать CALayers - PullRequest
       47

Печать CALayers

3 голосов
/ 05 мая 2010

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

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

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

Ответы [ 2 ]

5 голосов
/ 07 мая 2010

Чтобы обойти проблемы с макетом, а также тот факт, что использование -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);
}

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

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

0 голосов
/ 06 мая 2010

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

Я бы хотел знать, что я не прав.

...