Drawing Thumbnails and Previews In a Graphics Context

For previews or thumbnails of documents that consist primarily or solely of graphics and images, the best approach a generator can take is to draw the image of that document in a graphics context provided by Quick Look. The generator draws the document images directly in the client—the graphics context acts as a kind of window onto a surface of the client application. By doing this, you can avoid the overhead of creating and compressing an image into a native type and then requiring the client to decompress and load it on their end. Three graphics contexts are available, each for a different kind of document:

“Drawing Document Images in a Graphics Context” describes how to draw a thumbnail or preview for the first two situations. “Drawing Previews in a PDF Context” discusses the third kind of graphics context and explains how to use it.

Drawing Document Images in a Graphics Context

The strategy for drawing single-page previews and thumbnails in a graphics context is the same. Implement the appropriate callback function—GenerateThumbnailForURL or GeneratePreviewForURL—to read the given document (located by the CFURLRef parameter) into memory. Then get the Quick Look graphics context with a call to QLThumbnailRequestCreateContext or QLPreviewRequestCreateContext and draw the thumbnail or preview image in the provided context. Listing 5-1 shows the code for generating a preview of a Sketch document.

Listing 5-1  Drawing a Sketch preview in a Quick Look graphics context

OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
{
    @autoreleasepool{
        // Create and read the document file
        SKTDrawDocument* document = [[SKTDrawDocument alloc] init];
 
        if (![document readFromURL:(NSURL *)url ofType:(NSString *)contentTypeUTI]) {
            return noErr;
        }
 
        NSSize canvasSize = [document canvasSize];
 
        // Preview will be drawn in a vectorized context
        CGContextRef cgContext = QLPreviewRequestCreateContext(preview, *(CGSize *)&canvasSize, false, NULL);
        if(cgContext) {
            NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithGraphicsPort:(void *)cgContext flipped:YES];
            if(context) {
                [document drawDocumentInContext:context];
            }
            QLPreviewRequestFlushContext(preview, cgContext);
            CFRelease(cgContext);
        }
    }
    return noErr;
}

Before you draw the preview or thumbnail in the provided graphics context, make sure you save the current context and then restore that context when you’re finished drawing. You should then flush the context with QLPreviewRequestFlushContext or QLThumbnailRequestFlushContext and release it as shown in the above example.

The QLPreviewRequestCreateContext and QLThumbnailRequestCreateContext functions have identical sets of parameters. The first parameter identifies the preview request or thumbnail request object passed into the callback. The other parameters have a more direct bearing on the created graphics context.

A generator implementing the GenerateThumbnailForURL callback might be passed in the options directory a floating-point value that specifies how much Quick Look is scaling the thumbnail image. (You can access this value using the kQLThumbnailOptionScaleFactorKey key.). If you a drawing a vector image for a thumbnail using the graphics context returned from QLThumbnailRequestCreateContext, you don’t have to worry about scaling the image; just draw it normally in the the given size, which is in points. Quick Look creates a context with the specified size multiplied by the scale factor in pixels but also applies the appropriate affine transform so that the drawing context appears to the generator to be of the stated size.

Drawing Previews in a PDF Context

If your application has documents that (potentially) have more than one page of vector graphics, you should consider using the QLPreviewRequestCreatePDFContext function to create the graphics context for drawing the preview in. This function returns a graphics context suited for PDF content. The procedure is similar to the one described in “Drawing Document Images in a Graphics Context.” However, there are some important differences:

As with QLPreviewRequestCreateContext, when you have finished drawing the preview, be sure to call QLPreviewRequestFlushContext.