OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize)
{
    // load the actual file
    CFDataRef fileData = nil;
    CFDictionaryRef propertyDictionary = nil;
    SInt32 errorCode;
    if (CFURLCreateDataAndPropertiesFromResource(NULL, url, &fileData, &propertyDictionary, nil, &errorCode)) {
        
        CFIndex dataLength = CFDataGetLength(fileData);
        UInt8 *bytes = (UInt8 *)CFDataGetBytePtr(fileData);
        long pages = dataLength / ONE_LCD_FRAME_BYTESIZE;
        CGSize lcdSize = CGSizeMake(LCD_FRAME_PIXEL_WIDTH, LCD_FRAME_PIXEL_HEIGHT * pages);
        CGContextRef cgContext = QLThumbnailRequestCreateContext(thumbnail, lcdSize, true, NULL);
        if(cgContext) {
            
            CGColorRef lcdForegroundColor = CGColorCreateGenericRGB(0.467, 0.522, 0.047, 1.000);
            CGColorRef lcdBackgroundColor = CGColorCreateGenericRGB(0.227, 0.192, 0.000, 1.000);
            CGContextSetFillColorWithColor(cgContext, lcdBackgroundColor);
            CGContextFillRect(cgContext, CGRectMake(0,0,lcdSize.width,lcdSize.height));
            
            CGPoint origin = CGPointMake(0,0);
            while (pages-- > 0) {
                CGContextSetFillColorWithColor(cgContext, lcdForegroundColor);
                //                CGContextFillRect(cgContext, CGRectMake(origin.x,origin.y,10,10));
                for (int y=0;y<9;y++) {
                    for (int x=0; x < LCD_FRAME_PIXEL_WIDTH; x++) {
                        UInt8 byte = bytes[y*LCD_FRAME_PIXEL_WIDTH + (LCD_FRAME_PIXEL_WIDTH - x - 1)];
                        if (byte > 0) {
                            UInt8 byteMask = 1;
                            for (int littleY = 0; littleY < 8; littleY++) {
                                if ((byte & (byteMask << littleY))) {
                                    CGContextFillRect(cgContext, CGRectMake(origin.x + x,origin.y + y*8 + littleY,1,1));
                                }
                            }
                        }
                    }
                }
                origin.y += 68;
                bytes    += ONE_LCD_FRAME_BYTESIZE;
            }
            
            // When we are done with our drawing code QLPreviewRequestFlushContext() is called to flush the context
            QLThumbnailRequestFlushContext(thumbnail, cgContext);
        }
        CFRelease(cgContext);
        CFRelease(fileData);
        CFRelease(propertyDictionary);
    }
    return noErr;
}
Esempio n. 2
0
OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize)
{
	if (url == NULL)
	{
		return -1;
	}
	
	//fprintf(stderr, "GenerateThumbnailForURL\n");
	//CFShow(url);
	//fprintf(stderr, "maxSize: %fx%f\n", maxSize.width, maxSize.height);
	if ((maxSize.width == 200.0f) && (maxSize.height == 202.0f))
	{
		// hack to keep atPeek preview nice
		maxSize.height = 200.0f;
	}
	//fprintf(stderr, "maxSize: %fx%f\n", maxSize.width, maxSize.height);
	//CFShow(options);
	
	Boolean opaque = false;
	if (CFDictionaryGetValue(options, CFSTR("opaque")) != NULL)
	{
		opaque = CFBooleanGetValue(CFDictionaryGetValue(options, CFSTR("opaque")));
	}
	
	CGImageRef imageRef = GetPngImage(url, contentTypeUTI);
	if (imageRef != NULL)
	{
		CGRect imageRect = CGRectMake(0, 0, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
		float ratio = imageRect.size.width / imageRect.size.height;
		//fprintf(stderr, "imageSize: %dx%d, ratio: %f\n", (int)CGImageGetWidth(imageRef), (int)CGImageGetHeight(imageRef), ratio);
		if ((imageRect.size.width > maxSize.width) || (imageRect.size.height > maxSize.height))
		{
			if (imageRect.size.width > imageRect.size.height)
			{
				imageRect.size.width = maxSize.width;
				imageRect.size.height = maxSize.height/ratio;
			}
			else
			{
				imageRect.size.width = maxSize.width*ratio;
				imageRect.size.height = maxSize.height;
			}
		}
		imageRect.origin.x = (int)(((maxSize.width - imageRect.size.width) / 2.0) + 0.5);
		imageRect.origin.y = (int)(((maxSize.height - imageRect.size.height) / 2.0) + 0.5);
		//fprintf(stderr, "imageRect: %f,%f %fx%f\n", imageRect.origin.x , imageRect.origin.y, imageRect.size.width, imageRect.size.height);
		
		CGContextRef cgContext = QLThumbnailRequestCreateContext(thumbnail, maxSize, TRUE, NULL);
		if (cgContext != NULL)
		{
			CGContextSaveGState(cgContext);
			{
				if (opaque == 1)
				{
					CGRect contextRect = CGRectMake(0, 0, maxSize.width, maxSize.height);
					CGContextSetRGBFillColor(cgContext, 0.57, 0.57, 0.57, 1);
					CGContextFillRect(cgContext, contextRect);
				}
				
				CGContextDrawImage(cgContext, imageRect, imageRef);
			}
			CGContextRestoreGState(cgContext);
			
			QLThumbnailRequestFlushContext(thumbnail, cgContext);
			CFRelease(cgContext);
		}
		
		CFRelease(imageRef);
	}
	
    return noErr;
}
OSStatus GenerateThumbnailForURL(void *thisInterface, 
								 QLThumbnailRequestRef thumbnail,
								 CFURLRef url, CFStringRef contentTypeUTI, 
								 CFDictionaryRef options, CGSize maxSize)
{
	CGFloat minCartDrawSize = 64;
	CGFloat size = fmin(maxSize.width, maxSize.height);
	CGContextRef qlContext = NULL;
	if (size < minCartDrawSize) { 
		size = 32;
		qlContext = QLThumbnailRequestCreateContext(thumbnail, CGSizeMake(size,size), true, NULL);
	}
	else 
	{
		qlContext = QLThumbnailRequestCreateContext(thumbnail, CGSizeMake(size,size), false, NULL);
	}
	
	if (qlContext) {
		NDSHeader header;	
		NDSIcon icon;
		int pathlen = 2047;
		UInt8 path[pathlen+1];
		if (CFURLGetFileSystemRepresentation(url, true, path, pathlen)) { 
			
			if (size < minCartDrawSize) { // at smaller sizes we only draw the game icon at native size and let QL do the scaling
				parseNDSInfo(path, &header, &icon);
				CGImageRef image = CGImageCreateWithNDSIcon(&icon);
				if (image) {
					CGContextDrawImage(qlContext, CGRectMake(0, 0, size, size), image);
					CGImageRelease(image);
				}
			}
			else 
			{
				CGContextClearRect(qlContext, CGRectMake(0,0,size,size));
				
				// draw cartridge background
				CFURLRef bgURL = CFBundleCopyResourceURL(CFBundleGetBundleWithIdentifier(
																						 CFSTR("net.mironer.nds.quicklookgenerator")), CFSTR("background"), CFSTR("png"), NULL);
				if (bgURL) {
					CGDataProviderRef bgPNG = CGDataProviderCreateWithURL(bgURL);
					if (bgPNG) {
						CGImageRef bg = CGImageCreateWithPNGDataProvider(bgPNG, NULL, true, kCGRenderingIntentDefault);
						if (bg) {
							CGContextDrawImage(qlContext, CGRectMake(0, 0, size, size), bg);				
							CGImageRelease(bg);
						}
						CGDataProviderRelease(bgPNG);
					}
					CFRelease(bgURL);
				}			
				
				// draw game icon
				parseNDSInfo(path, &header, &icon);
				CGImageRef image = CGImageCreateWithNDSIcon(&icon);
				if (image) {
					CGContextDrawImage(qlContext, CGRectMake(size / 5, size / 5, size * 3 / 5, size * 3 / 5), image);
					CGImageRelease(image);
				}
				
				// draw cartridge overlay
				CFURLRef ovrURL = CFBundleCopyResourceURL( 
														  CFBundleGetBundleWithIdentifier(
																						  CFSTR("net.mironer.nds.quicklookgenerator")), CFSTR("overlay"), CFSTR("png"), NULL);
				if (ovrURL) {
					CGDataProviderRef ovrPNG = CGDataProviderCreateWithURL(ovrURL);
					if (ovrPNG) {
						CGImageRef ovr = CGImageCreateWithPNGDataProvider(ovrPNG, NULL, true, kCGRenderingIntentDefault);
						if (ovr) {
							CGContextDrawImage(qlContext, CGRectMake(0, 0, size, size), ovr);				
							CGImageRelease(ovr);
						}
						CGDataProviderRelease(ovrPNG);
					}
					CFRelease(ovrURL);
				}			
				
				// draw serial number
				CFStringRef serial = CFStringCreateWithSerialNumber(&header);
				CFAttributedStringRef aString = CFAttributedStringCreate(kCFAllocatorDefault, serial, NULL);
				CFMutableAttributedStringRef attrStr = CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 128, aString);
				CFIndex len =  CFAttributedStringGetLength(attrStr);
				CTFontRef font = CTFontCreateWithName(CFSTR("Lucida Sans"), size / 16, NULL);
				CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, len), kCTFontAttributeName, font);		
				
				CTTextAlignment rightAlign = kCTRightTextAlignment;
				CTParagraphStyleSetting styleSettings[] = { {kCTParagraphStyleSpecifierAlignment, sizeof(rightAlign), &rightAlign} };
				CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(styleSettings, 1);
				CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, len), kCTParagraphStyleAttributeName, paragraphStyle);
				
				CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrStr);
				CFRelease(attrStr);
				CFRelease(aString);
				CFRelease(serial);
				CFRelease(font);
				
				CGMutablePathRef path = CGPathCreateMutable();
				CGPathAddRect(path, NULL, CGRectMake(-size * 1.55 / 8, -size * 6.1 / 8, size, size));			
				CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
				CTFrameDraw(frame, qlContext);
				CFRelease(frame);
				CFRelease(framesetter); 
				CFRelease(paragraphStyle);
				CFRelease(path);
			}
		}
		QLThumbnailRequestFlushContext(thumbnail, qlContext);
        CFRelease(qlContext);
    }
    return noErr;
}