예제 #1
0
int generatePages(const char *documentPath) {
	int error = 0;
	CFStringRef path = CFStringCreateWithCString(
		NULL, documentPath, kCFStringEncodingUTF8
	);
	CFURLRef url = CFURLCreateWithFileSystemPath(
		NULL, path, kCFURLPOSIXPathStyle, 0
	);
	CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(url);

	if (document != NULL) {
		size_t lastPageIndex = CGPDFDocumentGetNumberOfPages(document) + 1;
		CFStringRef pdfPath = CFSTR("document.pdf");
		CFURLRef pdfUrl = CFURLCreateWithFileSystemPath(
			NULL, pdfPath, kCFURLPOSIXPathStyle, 0
		);
		CGContextRef context = CGPDFContextCreateWithURL(pdfUrl, NULL, NULL);

		printf("Compressing PDF\n");
		for(size_t pageIndex = 1; pageIndex < lastPageIndex; ++pageIndex) {
			CGPDFPageRef page = CGPDFDocumentGetPage(document, pageIndex);
			const CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox);

			printf("Adding page %lu\n", pageIndex);
			CGContextBeginPage(context, &cropBox);
			CGContextDrawPDFPage(context, page);
			CGContextEndPage(context);
		}

		CGContextRelease(context);
		if (pdfUrl != NULL) CFRelease(pdfUrl);
		if (pdfPath != NULL) CFRelease(pdfPath);
		CGPDFDocumentRelease(document);
	} else {
		fprintf(stderr, "Cannot open PDF document\n");
		error = 1;
	}

	if(url != NULL) CFRelease(url);
	if(path != NULL) CFRelease(path);

	return error;
}
예제 #2
0
/* Draw the source PDF document into the context and then draw the stamp PDF document
on top of it. When drawing the stamp on top, place it along the diagonal from the lower
left corner to the upper right corner and center its media rect to the center of that
diagonal. */
void StampWithPDFDocument(CGContextRef context, 
			CGPDFDocumentRef sourcePDFDoc, 
			CGPDFDocumentRef stampFileDoc, CGRect stampMediaRect)
{
    CGRect pageRect;
    float angle;
    size_t i, numPages = CGPDFDocumentGetNumberOfPages(sourcePDFDoc);
    
    // Loop over document pages and stamp each one appropriately.
    for(i = 1 ; i <= numPages ; i++)
    {
		// Use the page rectangle of each page from the source to compute
		// the destination media box for each page and the location of
		// the stamp.
		CGRect pageRect = CGPDFDocumentGetMediaBox(sourcePDFDoc, i);
		CGContextBeginPage(context, &pageRect);
		CGContextSaveGState(context);
			// Clip to the media box of the page.
			CGContextClipToRect(context, pageRect);	    
			// First draw the content of the source document.
			CGContextDrawPDFDocument(context, pageRect, sourcePDFDoc, i);
			// Translate to center of destination rect, that is the center of 
			// the media box of content to draw on top of.
			CGContextTranslateCTM(context, 
				pageRect.size.width/2, pageRect.size.height/2);
			// Compute angle of the diagonal across the destination page.
			angle = atan(pageRect.size.height/pageRect.size.width);
			// Rotate by an amount so that drawn content goes along a diagonal
			// axis across the page.
			CGContextRotateCTM(context, angle);
			// Move the origin so that the media box of the PDF to stamp
			// is centered around center point of destination.
			CGContextTranslateCTM(context, 
			-stampMediaRect.size.width/2, 
			-stampMediaRect.size.height/2);
			// Now draw the document to stamp with on top of original content.
			CGContextDrawPDFDocument(context, stampMediaRect, 
					stampFileDoc, 1);
		CGContextRestoreGState(context);
		CGContextEndPage(context);
    }
}
예제 #3
0
static void quartzgen_begin_page(GVJ_t *job)
{
	CGRect bounds = CGRectMake(0.0, 0.0, job->width, job->height);
	
	if (!job->context) {
		
		switch (job->device.id) {
		
		case FORMAT_PDF:
			{
				/* create the auxiliary info for PDF content, author and title */
				CFStringRef auxiliaryKeys[] = {
					kCGPDFContextCreator,
					kCGPDFContextTitle
				};
				CFStringRef auxiliaryValues[] = {
					CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s %s"), job->common->info[0], job->common->info[1]),
					job->obj->type == ROOTGRAPH_OBJTYPE ?
						CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)job->obj->u.g->name, strlen(job->obj->u.g->name), kCFStringEncodingUTF8, false, kCFAllocatorNull)
						: CFSTR("")
				};
				CFDictionaryRef auxiliaryInfo = CFDictionaryCreate(
					kCFAllocatorDefault,
					(const void **)&auxiliaryKeys,
					(const void **)&auxiliaryValues,
					sizeof(auxiliaryValues)/sizeof(auxiliaryValues[0]),
					&kCFTypeDictionaryKeyCallBacks,
					&kCFTypeDictionaryValueCallBacks
				);
				
				/* create a PDF for drawing into */
				CGDataConsumerRef data_consumer = CGDataConsumerCreate(job, &device_data_consumer_callbacks);
				job->context = CGPDFContextCreate(data_consumer, &bounds, auxiliaryInfo);
				
				/* clean up */
				CGDataConsumerRelease(data_consumer);
				CFRelease(auxiliaryInfo);
				int i;
				for (i = 0; i < sizeof(auxiliaryValues)/sizeof(auxiliaryValues[0]); ++i)
					CFRelease(auxiliaryValues[i]);
			}
			break;
		
		default: /* bitmap formats */
			{	
				size_t bytes_per_row = (job->width * BYTES_PER_PIXEL + BYTE_ALIGN) & ~BYTE_ALIGN;
				
				void* buffer = NULL;
				
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000
				
				/* iPhoneOS has no swap files for memory, so if we're short of memory we need to make our own temp scratch file to back it */
				
				size_t buffer_size = job->height * bytes_per_row;
				mach_msg_type_number_t vm_info_size = HOST_VM_INFO_COUNT;
				vm_statistics_data_t vm_info;
				
				if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_info, &vm_info_size) != KERN_SUCCESS
					|| buffer_size * 2 > vm_info.free_count * vm_page_size)
				{
					FILE* temp_file = tmpfile();
					if (temp_file)
					{
						int temp_file_descriptor = fileno(temp_file);
						if (temp_file_descriptor >= 0 && ftruncate(temp_file_descriptor, buffer_size) == 0)
						{
							buffer = mmap(
								NULL,
								buffer_size,
								PROT_READ | PROT_WRITE,
								MAP_FILE | MAP_SHARED,
								temp_file_descriptor,
								0);
							if (buffer == (void*)-1)
								buffer = NULL;
						}
						fclose(temp_file);
					}
				}
				if (!buffer)
					buffer = mmap(
						NULL,
						buffer_size,
						PROT_READ | PROT_WRITE,
						MAP_ANON| MAP_SHARED,
						-1,
						0);				
#endif				
				
				/* create a true color bitmap for drawing into */
				CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
				job->context = CGBitmapContextCreate(
					buffer,							/* data: MacOSX lets system allocate, iPhoneOS use manual memory mapping */
					job->width,						/* width in pixels */
					job->height,					/* height in pixels */
					BITS_PER_COMPONENT,				/* bits per component */
					bytes_per_row,					/* bytes per row: align to 16 byte boundary */
					color_space,					/* color space: device RGB */
					kCGImageAlphaPremultipliedFirst	/* bitmap info: premul ARGB has best support in OS X */
				);
				job->imagedata = CGBitmapContextGetData((CGContextRef)job->context);
				
				/* clean up */
				CGColorSpaceRelease(color_space);
			}
			break;
		}
		
	}
	
	/* start the page (if this is a paged context) and graphics state */
	CGContextRef context = (CGContextRef)job->context;
	CGContextBeginPage(context, &bounds);
	CGContextSaveGState(context);
	CGContextSetMiterLimit(context, 1.0);
	CGContextSetLineJoin(context, kCGLineJoinRound);
	
	/* set up the context transformation */
	CGContextScaleCTM(context, job->scale.x, job->scale.y);
	CGContextRotateCTM(context, -job->rotation * M_PI / 180.0);
	CGContextTranslateCTM(context, job->translation.x, job->translation.y);
}