void drawWithColorBlendMode(CGContextRef context, CFURLRef url)
{
    // A pleasant green color.
    float green[4] = { 0.584, 0.871, 0.318, 1.0 }; 
    CGRect insetRect, pdfRect;
    
    // Create a CGPDFDocument object from the URL.
    CGPDFDocumentRef pdfDoc = CGPDFDocumentCreateWithURL(url);
    if(pdfDoc == NULL){
		fprintf(stderr, "Couldn't create CGPDFDocument from URL!\n");
		return;
    }
    // Obtain the media box for page 1 of the PDF document.
    pdfRect = CGPDFDocumentGetMediaBox(pdfDoc, 1);
    // Set the origin of the rectangle to (0,0).
    pdfRect.origin.x = pdfRect.origin.y = 0;
    
    // Graphic 1, the left portion of the figure.
    CGContextTranslateCTM(context, 20, 10 + CGRectGetHeight(pdfRect)/2);
    
    // Draw the PDF document.
    CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1);
    
    // Set the fill color space to that returned by getTheCalibratedRGBColorSpace.
    CGContextSetFillColorSpace(context, getTheCalibratedRGBColorSpace());
    // Set the fill color to green.
    CGContextSetFillColor(context, green);
    
    // Graphic 2, the top-right portion of the figure.
    CGContextTranslateCTM(context, CGRectGetWidth(pdfRect) + 10, 
				    CGRectGetHeight(pdfRect)/2 + 10);

    // Draw the PDF document again.
    CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1);

    // Make a fill rectangle that is the same size as the PDF document
    // but inset each side by 80 units in x and 20 units in y.
    insetRect = CGRectInset(pdfRect, 80, 20);
    // Fill the rectangle with green. Because the fill color is opaque and
    // the blend mode is Normal, this obscures the drawing underneath. 
    CGContextFillRect(context, insetRect);
    
    // Graphic 3, the bottom-right portion of the figure.
    CGContextTranslateCTM(context, 0, -(10 + CGRectGetHeight(pdfRect)));

    // Draw the PDF document again.
    CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1);
    
    // Set the blend mode to kCGBlendModeColor which will
    // colorize the destination with subsequent drawing.
    CGContextSetBlendMode(context, kCGBlendModeColor);
    // Draw the rectangle on top of the PDF document. The portion of the
    // background that is covered by the rectangle is colorized
    // with the fill color.
    CGContextFillRect(context, insetRect);

    // Release the CGPDFDocumentRef the code created.
    CGPDFDocumentRelease(pdfDoc);
}
void TilePDFNoBuffer(CGContextRef context, CFURLRef url)
{
    // The amount of area to tile should really be based on the 
    // window/document. Here it is hard coded to a US Letter
    // size document. This may draw too many or too few tiles
    // for the area actually being filled.
    float fillwidth = 612., fillheight = 792.;
    float tileX, tileY, tileOffsetX, tileOffsetY, extraOffset = 6;
    float w, h;
    CGPDFDocumentRef pdfDoc = getThePDFDoc(url, &tileX, &tileY);
    if(pdfDoc == NULL){
	    fprintf(stderr, "Couldn't get the PDF document!\n");
	    return;
    }

#if DOSCALING
    // Make the tiles 1/3 the size of the PDF document.
    tileX /= 3;
    tileY /= 3;
	extraOffset /= 3;
#endif

    // Space the tiles by the tile width and height
    // plus extraOffset units in each dimension.
    tileOffsetX = extraOffset + tileX;
    tileOffsetY = extraOffset + tileY;

    // Tile the PDF document.
    for(h = 0; h < fillheight ; h += tileOffsetY)
		for(w = 0; w < fillwidth ; w += tileOffsetX){
			CGContextDrawPDFDocument(context, 
				CGRectMake(w, h, tileX, tileY), pdfDoc, 1);
		}
}
void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op)
{
    if (!m_document || m_currentPage == -1)
        return;

    context->save();

    context->setCompositeOperation(op);

    float hScale = dstRect.width() / srcRect.width();
    float vScale = dstRect.height() / srcRect.height();

    // Scale and translate so the document is rendered in the correct location,
    // including accounting for the fact that a GraphicsContext is always flipped
    // and doing appropriate flipping.
    CGContextTranslateCTM(context->platformContext(), dstRect.x() - srcRect.x() * hScale, dstRect.y() - srcRect.y() * vScale);
    CGContextScaleCTM(context->platformContext(), hScale, vScale);
    CGContextScaleCTM(context->platformContext(), 1, -1);
    CGContextTranslateCTM(context->platformContext(), 0, -srcRect.height());
    CGContextClipToRect(context->platformContext(), CGRectIntegral(srcRect));

    // Rotate translate image into position according to doc properties.
    adjustCTM(context);

    // Media box may have non-zero origin which we ignore. Pass 1 for the page number.
    CGContextDrawPDFDocument(context->platformContext(), FloatRect(FloatPoint(), m_mediaBox.size()),
        m_document, m_currentPage + 1);
    
    context->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}
/* 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);
    }
}
示例#5
0
int main (int argc, const char * argv[])
{
    if(argc >= 2) {
        CGPDFDocumentRef doc = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithFilename(argv[1]));
        size_t pages = CGPDFDocumentGetNumberOfPages(doc);
        
        printf("%lu pages\n", pages);
        
        for(size_t i = 1; i <= pages; i++) {
            char filename[1024];
            
            snprintf(filename, 1024, "%s.%03lu.png", argv[1], i);
            
            printf("writing file: %s\n", filename);
         
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            CGContextRef context = CGBitmapContextCreate(NULL, SIZE, SIZE, 8, 4 * SIZE, colorSpace, kCGImageAlphaPremultipliedLast);
            CGColorSpaceRelease(colorSpace);
            
            CGContextDrawPDFDocument(context, CGRectMake(0, 0, SIZE, SIZE), doc, (int)i);
            
            CGImageRef image = CGBitmapContextCreateImage(context);
            
            CGImageDestinationRef dest = CGImageDestinationCreateWithURL(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFStringCreateWithCString(kCFAllocatorDefault, filename, kCFStringEncodingASCII), kCFURLPOSIXPathStyle, false), kUTTypePNG, 1, NULL);
            
            CGImageDestinationAddImage(dest, image, NULL);
            
            CGImageDestinationFinalize(dest);
            
            CGImageRelease(image);
            CGContextRelease(context);
        }
        
        CGPDFDocumentRelease(doc);
    } else {
        printf("pdf2png [filename]\n");
        return 1;
    }
    
    return 0;
}
static CGLayerRef createLayerWithImageForContext(CGContextRef c, CFURLRef url)
{
    CGSize layerSize;
    CGLayerRef layer;
    CGPDFDocumentRef pdfDoc = getThePDFDoc(url, &layerSize.width, &layerSize.height);
    if(pdfDoc == NULL){
		return NULL;
    }

#if DOSCALING
    // Make the layer 1/3 the size of the PDF document.
    layerSize.width /= 3;
    layerSize.height /= 3;
#endif

    // Create the layer to draw into.
    layer = CGLayerCreateWithContext(c, layerSize, NULL);
    if(layer == NULL)
		return NULL;
	
    // Get the context corresponding to the layer. Note
    // that this is a 'Get' function so the code must
    // not release the context.
    CGContextRef layerContext = CGLayerGetContext(layer);
    if(layerContext == NULL){
		CGLayerRelease(layer);
		return NULL;
    }
    
    // Draw the PDF document into the layer.
    CGContextDrawPDFDocument(layerContext,
		CGRectMake(0, 0, layerSize.width, layerSize.height), pdfDoc, 1);
    
    // Now the layer has the contents needed.
    return layer;
}
void TilePDFWithOffscreenBitmap(CGContextRef context, CFURLRef url)
{
    // Again this should really be computed based on
    // the area intended to be tiled.
    float fillwidth = 612., fillheight = 792.;
    float tileX, tileY, tileOffsetX, tileOffsetY, extraOffset = 6;
    float w, h;
    CGContextRef bitmapContext;
    Boolean useDisplayColorSpace;
    Boolean needTransparentBitmap;

    CGPDFDocumentRef pdfDoc = getThePDFDoc(url, 
				    &tileX,
				    &tileY);
    if(pdfDoc == NULL){
	    fprintf(stderr, "Couldn't get the PDF document!\n");
	    return;
    }

#if DOSCALING
    // Make the tiles 1/3 the size of the PDF document.
    tileX /= 3;
    tileY /= 3;
	extraOffset /= 3;
#endif

    // Space the tiles by the tile width and height
    // plus extraOffset units in each dimension.
    tileOffsetX = extraOffset + tileX;
    tileOffsetY = extraOffset + tileY;
    
    // Since the bitmap context is for use with the display
    // and should capture alpha, these are the values
    // to pass to createRGBBitmapContext.
    useDisplayColorSpace = true;
    needTransparentBitmap = true;
    bitmapContext = createRGBBitmapContext(tileX, tileY, 
					useDisplayColorSpace, 
					needTransparentBitmap);
    if(bitmapContext == NULL){
		fprintf(stderr, "Couldn't create bitmap context!\n");
		return;
    }

    // Draw the PDF document one time into the bitmap context.
    CGContextDrawPDFDocument(bitmapContext, 
		    CGRectMake(0, 0, tileX, tileY), pdfDoc, 1);

    // Create an image from the raster data. Calling
	// createImageFromBitmapContext gives up ownership
	// of the raster data used by the context.
    CGImageRef image = createImageFromBitmapContext(bitmapContext);

	// Release the context now that the image is created.
    CGContextRelease(bitmapContext);

    if(image == NULL){
		return;
    }
    
    // Now tile the image.
    for(h = 0; h < fillheight ; h += tileOffsetY)
		for(w = 0; w < fillwidth ; w += tileOffsetX){
			CGContextDrawImage(context, CGRectMake(w, h, tileX, tileY), image);
		}
	
    CGImageRelease(image);
}