Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

MrFusion

macrumors 6502a
Original poster
Jun 8, 2005
613
0
West-Europe
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);
}
 

MrFusion

macrumors 6502a
Original poster
Jun 8, 2005
613
0
West-Europe
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.