0

I converted in PDF an NSView (PDFContentView:NSView) with the method NSPrintOperation. This NSView contains 2 subviews (Drawing:NSView). This subviews are drawn using the drawRect method.

The expected result is correct when I display my view in a NSWindow :

enter image description here

But in the PDF file, the second subview seem to be included in the first :

enter image description here

It seems to be a problem of layers, but when I change setWantsLayer: to NO, it's the same result.

Nota : I found answers that recommend to convert the subviews, which are drawn by drawRect method, into NSImage and then add it to the View. But This solution don't fit my problem, because I need to keep the possibility of zooming in the pdf without pixelising the subviews.

Thank you for your help.

Here is my code :

The method to convert my pdfContentView in PDF :

- (void)createPDFWithPages
{
    NSPrintInfo *printInfo;
    NSPrintInfo *sharedInfo;
    NSPrintOperation *printOp;
    NSMutableDictionary *printInfoDict;
    NSMutableDictionary *sharedDict;

    sharedInfo = [NSPrintInfo sharedPrintInfo];
    sharedDict = [sharedInfo dictionary];
    printInfoDict = [NSMutableDictionary dictionaryWithDictionary:sharedDict];

    [printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition];

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *desktopURLArray = [fileManager URLsForDirectory:NSDesktopDirectory inDomains:NSUserDomainMask];
    NSURL *desktopURL = [desktopURLArray objectAtIndex:0];
    NSString *fileName = [NSString stringWithFormat:@"/%@", @"myPDF.pdf"];
    NSURL *fileURL = [NSURL fileURLWithPath:[[desktopURL path] stringByAppendingString:fileName]];

    [printInfoDict setObject:[fileURL path] forKey:NSPrintSavePath];

    printInfo = [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
    [printInfo setTopMargin:30.0];
    [printInfo setBottomMargin:30.0];
    [printInfo setLeftMargin:30.0];
    [printInfo setRightMargin:30.0];
    [printInfo setHorizontalPagination: NSAutoPagination];
    [printInfo setVerticalPagination: NSAutoPagination];
    [printInfo setVerticallyCentered:NO];

    printOp = [NSPrintOperation printOperationWithView:pdfContentView printInfo:printInfo];

    [printOp setShowsPrintPanel:NO];
    [printOp runOperation];
}

PDFContentView.m :

#import "PDFContentView.h"
#import "Drawing.h"

@interface PDFContentView ()
{
    Drawing *drawing1;
    Drawing *drawing2;
}
@end

@implementation PDFContentView

- (id)init
{
    if(self = [super init])
    {
        self.frame = NSMakeRect(10, 10, 520, 780); //page size = (520, 780)
        [self setWantsLayer:YES];
        self.layer.backgroundColor = [NSColor whiteColor].CGColor;

        drawing1 = [[Drawing alloc] initWithFrame:NSMakeRect(0, 20, 50, 50)];
        [drawing1 setBackgroundColor:[NSColor greenColor]];
        [self addSubview:drawing1];

        drawing2 = [[Drawing alloc] initWithFrame:NSMakeRect(30, 0, 50, 50)];
        [drawing2 setBackgroundColor:[NSColor yellowColor]];
        [self addSubview:drawing2];
    }

    return self;
}

- (BOOL)isFlipped
{
    return YES;
}

@end

Drawing.m :

#import "Drawing.h"

@interface Drawing ()
{
    NSColor *backgrounColor;
}
@end

@implementation Drawing

- (id)initWithFrame:(NSRect)contentRect
{
    if(self = [super initWithFrame:(NSRect)contentRect])
    {
        self.frame = contentRect;
        [self setWantsLayer:YES];

        backgrounColor = [[NSColor alloc] init];
        backgrounColor = [NSColor colorWithCalibratedRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:255.0/255.0];
    }

    return self;
}

- (BOOL)isFlipped
{
    return YES;
}

- (void)setBackgroundColor:(NSColor*)color;
{
    backgrounColor = color;

    [self setNeedsDisplay:YES];
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];

    CGMutablePathRef path00 = CGPathCreateMutable();

    CGPathMoveToPoint(path00, NULL, 0, 0);
    CGPathAddLineToPoint(path00, NULL, self.frame.size.width, 0);
    CGPathAddLineToPoint(path00, NULL, self.frame.size.width, self.frame.size.height);
    CGPathAddLineToPoint(path00, NULL, 0, self.frame.size.height);
    CGPathCloseSubpath(path00);

    CGContextSaveGState(context);
    CGContextAddPath(context, path00);
    CGContextSetFillColorWithColor(context, backgrounColor.CGColor);
    CGContextFillPath(context);
    CGContextRestoreGState(context);


    CGRect borderRect = NSMakeRect(0.5, 0.5, 24, 24);
    CGMutablePathRef borderPath = CGPathCreateMutable();
    CGPathAddRect(borderPath, NULL, borderRect);
    CGPathCloseSubpath(borderPath);

    CGContextSaveGState(context);
    CGContextAddPath(context, borderPath);
    CGContextSetStrokeColorWithColor(context, [NSColor redColor].CGColor);
    CGContextSetLineWidth(context, 1);
    CGContextStrokePath(context);
    CGContextRestoreGState(context); // => Missing funtion

    CGMutablePathRef path2 = CGPathCreateMutable();
    CGRect aRect = NSMakeRect(10, 11, 4, 4);
    CGPathAddRect(path2, NULL, aRect);
    CGPathCloseSubpath(path2);

    CGContextSaveGState(context);
    CGContextAddPath(context, path2);
    CGContextSetShouldAntialias(context, NO);
    CGContextSetStrokeColorWithColor(context, [NSColor blueColor].CGColor);
    CGContextSetLineWidth(context, 1);
    CGContextStrokePath(context);
    CGContextRestoreGState(context); // => Missing funtion
}

@end
  • Try a `CGContextRestoreGState` for each `CGContextSaveGState`. – Willeke Oct 27 '18 at 23:09
  • Not related to the issue: `NSView`s `dataWithPDFInsideRect:` is easier to use. – Willeke Oct 28 '18 at 03:22
  • @Willeke : Great ! It solve the problem. It was not a problem of layers, but simply a CGContextRestoreGState missing. Shame on me ! But it's strange that the NSView shown on NSWindow was good. Thanks a lot Willeke. Nota : I don't have the tick button to mark your answer as correct. – Jeff Dolphin Oct 28 '18 at 13:47

0 Answers0