CALayer to pdf

Discussion in 'Mac Programming' started by MrFusion, Aug 5, 2011.

  1. MrFusion macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #1
    Hi all

    I am trying to export a CALayer to a pdf file (or any other kind of image file).
    The code below, pieced together from google and Apple docs, generates a pdf file with two white pages. :)
    Unfortunately, even though drawInContext: is called, nothing is drawn into the pdf. :(
    If you have any idea what is missing, I am glad to hear it. :confused:

    The docs also mention bitmaps, but vector based pdf's are better, or not.

    Code:
    - (void) exportToPDF
    {
    	TestLayer *testLayer = [TestLayer layer];
    	[testLayer setFrame:CGRectMake(11, 11, 333, 444)];
    	[testLayer setBackgroundColor:CGColorCreateGenericRGB(1, 1, 1, 1)];
    	NSRect offscreenRect = NSMakeRect(0.0, 0.0, 500.0, 500.0);
    	CGContextRef myContextRef;
    	
    	[rootLayer addSublayer:testLayer];
    	
    #if 1	//pdf
    	
    	//create context
    	NSMutableData *pdfData = [[NSMutableData alloc] init];
    	CGDataConsumerRef pdfDataConsumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)pdfData);	
    	myContextRef = CGPDFContextCreate(pdfDataConsumer, &offscreenRect, NULL);
    	
    	CFMutableDictionaryRef pageDictionary =  pageDictionary = CFDictionaryCreateMutable(NULL, 0,
    																						&kCFTypeDictionaryKeyCallBacks,
    																						&kCFTypeDictionaryValueCallBacks);
    	CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, pdfData); //what is the point of this line?
    	
    	//draw into context
    	CGContextSaveGState(myContextRef);	
    
    	CGContextBeginPage(myContextRef, &offscreenRect);
    	[testLayer drawInContext:myContextRef];
    	CGContextEndPage(myContextRef);   
    
    	CGContextBeginPage(myContextRef, &offscreenRect);
    	[testLayer drawInContext:myContextRef];
    	CGContextEndPage(myContextRef);   
    
    	CGContextRestoreGState(myContextRef);
    	
    	//cleanup
    	CGPDFContextClose(myContextRef);
    	CGContextRelease(myContextRef);
    	CGDataConsumerRelease(pdfDataConsumer);
    	
    	
    	//create image
    	NSImage *img = [[NSImage alloc] initWithData:pdfData];
    	[pdfData writeToURL:[NSURL fileURLWithPath:@"/...aValidPath.../test.pdf"]  
    			 atomically:YES];
    	
    #endif
    }	
    
    -(void) drawInContext:(CGContextRef) myContext
    {
    	if (myContext) 
    		NSLog(@"draw %i",CGContextGetTypeID());
    	else
    		NSLog(@"no-draw");
    	
    	//draw line
    	CGMutablePathRef strikethrough = CGPathCreateMutable();
    	CGPathMoveToPoint(strikethrough, NULL, 10, 110);
    	CGPathAddLineToPoint(strikethrough, NULL, 411, 211);
    	CGContextSetLineWidth(myContext, 10);
    	
    	CGFloat redColour[4] = {1.0,0.0,0.0,1.0};	
    	CGContextSetStrokeColor(myContext, redColour);
    	
    	CGContextAddPath(myContext, strikethrough);
    	CGContextDrawPath(myContext, kCGPathStroke);
    	CGPathRelease(strikethrough);
    	
    	
    	//draw line 2
    	CGMutablePathRef seperationLine = CGPathCreateMutable();
    	CGPathMoveToPoint(seperationLine, NULL, 0, 0);
    	CGPathAddLineToPoint(seperationLine, NULL, 55, 44);
    	
    	//line properties
    	CGContextSetStrokeColorWithColor(myContext, CGColorCreateGenericRGB(1, 1, 0, 1));
    	CGContextSetLineWidth(myContext, 1);
    	
    	//draw
    	CGContextAddPath(myContext, seperationLine);
    	CGContextDrawPath(myContext, kCGPathStroke);
    	
    	//cleanup
    	CGPathRelease(seperationLine);
    }
    
    
     
  2. MrFusion thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #2
    Hi all,

    Problem solved. The problem was that no content was drawn.
    Replace the first two lines in the code fragment with the third line.

    Code:
    //	const CGFloat redColour[4] = {1.0,0.0,0.0,1.0};	
    //	CGContextSetStrokeColor(myContext,redColour);	
    	
    CGContextSetStrokeColorWithColor(myContext, CGColorCreateGenericRGB(1, 0, 0, 1));	
    
    To draw a background in the pdf file, you need this code fragment:
    Code:
    	CGMutablePathRef background = CGPathCreateMutable();
    	CGPathAddRect(background, NULL, rect);
    	CGContextSetFillColorWithColor(myContext, [self backgroundColor]);
    	CGContextAddPath(myContext, background);
    	CGContextDrawPath(myContext, kCGPathFill);
    	CGPathRelease(background);
    
    This duplicates part of the CALayer functionality. So, you probably want to check which type of context you are drawing in. isDrawingToScreen: and currentContextDrawingToScreen: can be used with an NSGraphicsContext. I didn't find any equivalents for CGContextRef, though.
     

Share This Page