void *quartz_new_layout(char* fontname, double fontsize, char* text)
{
	CFStringRef fontnameref = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)fontname, strlen(fontname), kCFStringEncodingUTF8, FALSE);
	CFStringRef textref = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)text, strlen(text), kCFStringEncodingUTF8, FALSE);
	CTLineRef line = NULL;
	
	if (fontnameref && textref) {
		/* set up the Core Text line */
		CTFontRef font = CTFontCreateWithName(fontnameref, fontsize, NULL);
		
		CFDictionaryRef attributes = CFDictionaryCreate(
			kCFAllocatorDefault,
			(const void**)&kCTFontAttributeName,
			(const void**)&font,
			1,
			&kCFTypeDictionaryKeyCallBacks,
			&kCFTypeDictionaryValueCallBacks);
		CFAttributedStringRef attributed = CFAttributedStringCreate(kCFAllocatorDefault, textref, attributes);
		line = CTLineCreateWithAttributedString(attributed);
		
		CFRelease(attributed);
		CFRelease(attributes);
		CFRelease(font);
	}
	
	if (textref)
		CFRelease(textref);
	if (fontnameref)
		CFRelease(fontnameref);
	return (void *)line;
}
Beispiel #2
0
void drawTextWithFeature(CGContextRef context, CTFontDescriptorRef fontDescriptor, CFStringRef feature, int value, CGPoint location)
{
    CGFloat fontSize = 25;
    CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, 1));
    CGContextSetTextPosition(context, location.x, location.y);

    CFNumberRef featureValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value);
    CFTypeRef featureDictionaryKeys[] = { kCTFontOpenTypeFeatureTag, kCTFontOpenTypeFeatureValue };
    CFTypeRef featureDictionaryValues[] = { feature, featureValue };
    CFDictionaryRef featureDictionary = CFDictionaryCreate(kCFAllocatorDefault, featureDictionaryKeys, featureDictionaryValues, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFRelease(featureValue);

    CFTypeRef featureSettingsValues[] = { featureDictionary };
    CFArrayRef fontFeatureSettings = CFArrayCreate(kCFAllocatorDefault, featureSettingsValues, 1, &kCFTypeArrayCallBacks);
    CFRelease(featureDictionary);

    CFTypeRef fontDescriptorKeys[] = { kCTFontFeatureSettingsAttribute };
    CFTypeRef fontDescriptorValues[] = { fontFeatureSettings };
    CFDictionaryRef fontDescriptorAttributes = CFDictionaryCreate(kCFAllocatorDefault, fontDescriptorKeys, fontDescriptorValues, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFRelease(fontFeatureSettings);

    CTFontDescriptorRef modifiedFontDescriptor = CTFontDescriptorCreateCopyWithAttributes(fontDescriptor, fontDescriptorAttributes);
    CFRelease(fontDescriptorAttributes);

    CTFontRef font = CTFontCreateWithFontDescriptor(modifiedFontDescriptor, fontSize, nullptr);
    CFRelease(modifiedFontDescriptor);

    CFMutableStringRef string = CFStringCreateMutable(kCFAllocatorDefault, 0);
    CFStringAppend(string, feature);
    CFStringAppend(string, value ? CFSTR("  (on)") : CFSTR(" (off)"));
    CFStringAppend(string, CFSTR(": ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));

    CGColorRef red = CGColorCreateGenericRGB(1, 0, 0, 1);
    CFTypeRef lineKeys[] = { kCTForegroundColorAttributeName };
    CFTypeRef lineValues[] = { red };
    CFDictionaryRef lineAttributes = CFDictionaryCreate(kCFAllocatorDefault, lineKeys, lineValues, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CGColorRelease(red);

    CFAttributedStringRef attributedString = CFAttributedStringCreate(kCFAllocatorDefault, string, lineAttributes);
    CFRelease(lineAttributes);
    CFRelease(string);

    CFMutableAttributedStringRef mutableAttributedString = CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 0, attributedString);
    CFRelease(attributedString);

    CTFontRef monospaceFont = CTFontCreateWithName(CFSTR("Courier"), fontSize, nullptr);
    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(0, 12), kCTFontAttributeName, monospaceFont);
    CFRelease(monospaceFont);

    CFAttributedStringSetAttribute(mutableAttributedString, CFRangeMake(12, 52), kCTFontAttributeName, font);
    CFRelease(font);

    CTLineRef line = CTLineCreateWithAttributedString(mutableAttributedString);
    CFRelease(mutableAttributedString);

    CTLineDraw(line, context);
    CFRelease(line);
}
Beispiel #3
0
static QFontEngine *loadFromDatabase(QFontDef &req, const QFontPrivate *d)
{
#if defined(QT_MAC_USE_COCOA)
    QCFString fontName = NULL;
#else
    ATSFontFamilyRef familyRef = 0;
    ATSFontRef fontRef = 0;
#endif

    QStringList family_list = familyList(req);

    const char *stylehint = styleHint(req);
    if (stylehint)
        family_list << QLatin1String(stylehint);

    // add QFont::defaultFamily() to the list, for compatibility with previous versions
    family_list << QApplication::font().defaultFamily();

    QMutexLocker locker(fontDatabaseMutex());
    QFontDatabasePrivate *db = privateDb();
    if (!db->count)
        initializeDb();
    for (int i = 0; i < family_list.size(); ++i) {
        for (int k = 0; k < db->count; ++k) {
            if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
                QByteArray family_name = db->families[k]->name.toUtf8();
#if defined(QT_MAC_USE_COCOA)
                QCFType<CTFontRef> ctFont = CTFontCreateWithName(QCFString(db->families[k]->name), 12, NULL);
                if (ctFont) {
                    fontName = CTFontCopyFullName(ctFont);
                    goto found;
                }
#else
                familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                if (familyRef) {
                    fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                    goto found;
                }
#endif
            }
        }
    }
found:
#ifdef QT_MAC_USE_COCOA
    if (fontName)
        return new QCoreTextFontEngineMulti(fontName, req, d->kerning);
#else
    if (familyRef) {
        QCFString actualName;
        if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
            req.family = actualName;
        return new QFontEngineMacMulti(familyRef, fontRef, req, d->kerning);
    }
#endif
    return NULL;
}
Beispiel #4
0
static void *font_renderer_ct_init(const char *font_path, float font_size)
{
   char err = 0;
   CFStringRef cf_font_path = NULL;
   CTFontRef face = NULL;
   ct_font_renderer_t *handle = (ct_font_renderer_t*)
      calloc(1, sizeof(*handle));

   if (!handle)
   {
      err = 1;
      goto error;
   }

   cf_font_path = CFStringCreateWithCString(NULL, font_path, kCFStringEncodingASCII);
   if (!cf_font_path)
   {
      err = 1;
      goto error;
   }

   face = CTFontCreateWithName(cf_font_path, font_size, NULL);

   if (!face)
   {
      err = 1;
      goto error;
   }

   if (!font_renderer_create_atlas(face, handle))
   {
      err = 1;
      goto error;
   }

error:
   if (err)
   {
      font_renderer_ct_free(handle);
      handle = NULL;
   }

   if (cf_font_path)
   {
      CFRelease(cf_font_path);
      cf_font_path = NULL;
   }
   if (face)
   {
      CFRelease(face);
      face = NULL;
   }

   return handle;
}
Beispiel #5
0
// This function is needed to work around a bug in Windows CG <rdar://problem/22703470>
void PlatformCALayer::drawTextAtPoint(CGContextRef context, CGFloat x, CGFloat y, CGSize scale, CGFloat fontSize, const char* text, size_t length) const
{
    auto matrix = CGAffineTransformMakeScale(scale.width, scale.height);
    auto font = adoptCF(CTFontCreateWithName(CFSTR("Helvetica"), fontSize, &matrix));
    CFTypeRef keys[] = { kCTFontAttributeName, kCTForegroundColorFromContextAttributeName };
    CFTypeRef values[] = { font.get(), kCFBooleanTrue };
    auto attributes = adoptCF(CFDictionaryCreate(kCFAllocatorDefault, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    auto string = adoptCF(CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(text), length, kCFStringEncodingUTF8, false, kCFAllocatorNull));
    auto attributedString = adoptCF(CFAttributedStringCreate(kCFAllocatorDefault, string.get(), attributes.get()));
    auto line = adoptCF(CTLineCreateWithAttributedString(attributedString.get()));
    CGContextSetTextPosition(context, x, y);
    CTLineDraw(line.get(), context);
}
Beispiel #6
0
static char *get_fallback(void *priv, const char *family, uint32_t codepoint)
{
    CFStringRef name = CFStringCreateWithBytes(
        0, (UInt8 *)family, strlen(family), kCFStringEncodingUTF8, false);
    CTFontRef font = CTFontCreateWithName(name, 0, NULL);
    uint32_t codepointle = OSSwapHostToLittleInt32(codepoint);
    CFStringRef r = CFStringCreateWithBytes(
        0, (UInt8*)&codepointle, sizeof(codepointle),
        kCFStringEncodingUTF32LE, false);
    CTFontRef fb = CTFontCreateForString(font, r, CFRangeMake(0, 1));
    CFStringRef cffamily = CTFontCopyFamilyName(fb);
    char *res_family = cfstr2buf(cffamily);

    SAFE_CFRelease(name);
    SAFE_CFRelease(font);
    SAFE_CFRelease(r);
    SAFE_CFRelease(fb);
    SAFE_CFRelease(cffamily);

    return res_family;
}
Beispiel #7
0
void QFontDatabase::load(const QFontPrivate *d, int script)
{
    // sanity checks
    if(!qApp)
        qWarning("QFont: Must construct a QApplication before a QFont");

    Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount);
    Q_UNUSED(script);

    QFontDef req = d->request;
    req.pixelSize = qt_mac_pixelsize(req, d->dpi);

    // set the point size to 0 to get better caching
    req.pointSize = 0;
    QFontCache::Key key = QFontCache::Key(req, QUnicodeTables::Common, d->screen);

    if(!(d->engineData = QFontCache::instance()->findEngineData(key))) {
        d->engineData = new QFontEngineData;
        QFontCache::instance()->insertEngineData(key, d->engineData);
    } else {
        d->engineData->ref.ref();
    }
    if(d->engineData->engine) // already loaded
        return;

    // set it to the actual pointsize, so QFontInfo will do the right thing
    req.pointSize = qRound(qt_mac_pointsize(d->request, d->dpi));

    QFontEngine *e = QFontCache::instance()->findEngine(key);
    if(!e && qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
        e = new QTestFontEngine(req.pixelSize);
        e->fontDef = req;
    }

    if(e) {
        e->ref.ref();
        d->engineData->engine = e;
        return; // the font info and fontdef should already be filled
    }

    //find the font
    QStringList family_list = familyList(req);

    const char *stylehint = styleHint(req);
    if (stylehint)
        family_list << QLatin1String(stylehint);

    // add QFont::defaultFamily() to the list, for compatibility with
    // previous versions
    family_list << QApplication::font().defaultFamily();

    ATSFontFamilyRef familyRef = 0;
    ATSFontRef fontRef = 0;

    QMutexLocker locker(fontDatabaseMutex());
    QFontDatabasePrivate *db = privateDb();
    if (!db->count)
        initializeDb();
    for(int i = 0; i < family_list.size(); ++i) {
        for (int k = 0; k < db->count; ++k) {
            if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
                QByteArray family_name = db->families[k]->name.toUtf8();
                familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                if (familyRef) {
                    fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
                    goto FamilyFound;
                } else {
#if defined(QT_MAC_USE_COCOA)
                    // ATS and CT disagrees on what the family name should be,
                    // use CT to look up the font if ATS fails.
                    QCFString familyName = QString::fromAscii(family_name);
                    QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL);
                    QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef);
                    QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute);

                    familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault);
                    if (familyRef) {
                        fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault);
                        goto FamilyFound;
                    }
#endif
                }
            }
        }
    }
FamilyFound:
    //fill in the engine's font definition
    QFontDef fontDef = d->request; //copy..
    if(fontDef.pointSize < 0)
	fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi);
    else
	fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi);
#if 0
    ItemCount name_count;
    if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) {
        ItemCount actualName_size;
        if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) {
            QByteArray actualName(actualName_size);
            if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size)
                fontDef.family = QString::fromUtf8(actualName);
        }
    }
#else
    {
        QCFString actualName;
        if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
            fontDef.family = actualName;
    }
#endif

#ifdef QT_MAC_USE_COCOA
    QFontEngine *engine = new QCoreTextFontEngineMulti(familyRef, fontRef, fontDef, d->kerning);
#elif 1
    QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning);
#else
    ATSFontFamilyRef atsFamily = familyRef;
    ATSFontFamilyRef atsFontRef = fontRef;

    FMFont fontID;
    FMFontFamily fmFamily;
    FMFontStyle fntStyle = 0;
    fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily);
    if (fmFamily == kInvalidFontFamily) {
        // Use the ATSFont then...
        fontID = FMGetFontFromATSFontRef(atsFontRef);
    } else {
        if (fontDef.weight >= QFont::Bold)
            fntStyle |= ::bold;
        if (fontDef.style != QFont::StyleNormal)
            fntStyle |= ::italic;

        FMFontStyle intrinsicStyle;
        FMFont fnt = 0;
        if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr)
           fontID = FMGetATSFontRefFromFont(fnt);
    }

    OSStatus status;

    const int maxAttributeCount = 5;
    ATSUAttributeTag tags[maxAttributeCount + 1];
    ByteCount sizes[maxAttributeCount + 1];
    ATSUAttributeValuePtr values[maxAttributeCount + 1];
    int attributeCount = 0;

    Fixed size = FixRatio(fontDef.pixelSize, 1);
    tags[attributeCount] = kATSUSizeTag;
    sizes[attributeCount] = sizeof(size);
    values[attributeCount] = &size;
    ++attributeCount;

    tags[attributeCount] = kATSUFontTag;
    sizes[attributeCount] = sizeof(fontID);
    values[attributeCount] = &fontID;
    ++attributeCount;

    CGAffineTransform transform = CGAffineTransformIdentity;
    if (fontDef.stretch != 100) {
        transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
        tags[attributeCount] = kATSUFontMatrixTag;
        sizes[attributeCount] = sizeof(transform);
        values[attributeCount] = &transform;
        ++attributeCount;
    }

    ATSUStyle style;
    status = ATSUCreateStyle(&style);
    Q_ASSERT(status == noErr);

    Q_ASSERT(attributeCount < maxAttributeCount + 1);
    status = ATSUSetAttributes(style, attributeCount, tags, sizes, values);
    Q_ASSERT(status == noErr);

    QFontEngine *engine = new QFontEngineMac(style, fontID, fontDef, /*multiEngine*/ 0);
    ATSUDisposeStyle(style);
#endif
    d->engineData->engine = engine;
    engine->ref.ref(); //a ref for the engineData->engine
    QFontCache::instance()->insertEngine(key, engine);
}
Beispiel #8
0
	Font::Font(const char *name,float size)
	{
		CFStringRef cfName = CFStringCreateWithCString(kCFAllocatorDefault,name,kCFStringEncodingUTF8);
		mFont = CTFontCreateWithName(cfName, size, NULL);
		CFRelease(cfName);
	}
Beispiel #9
0
draw__Font draw__new_font(const char *name, int size) {
  CFStringRef font_name = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8);
  draw__Font  font      = CTFontCreateWithName(font_name, size, NULL /* transform matrix */);
  CFRelease  (font_name);
  return      font;
}
Beispiel #10
0
bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
                                          bool fixedWidthOnly)
{
     wxArrayString fontFamilies ;

    wxUint32 macEncoding = wxMacGetSystemEncFromFontEnc(encoding) ;

    {
        CFArrayRef cfFontFamilies = nil;

#if wxOSX_USE_COCOA_OR_CARBON
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
        if ( UMAGetSystemVersion() >= 0x1060 )
            cfFontFamilies = CTFontManagerCopyAvailableFontFamilyNames();
        else
#endif
        {
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6)
            //
            // From Apple's QA 1471 http://developer.apple.com/qa/qa2006/qa1471.html
            //
            
            CFMutableArrayRef atsfontnames = CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);;
            
            ATSFontFamilyIterator theFontFamilyIterator = NULL;
            ATSFontFamilyRef theATSFontFamilyRef = 0;
            OSStatus status = noErr;
            
            // Create the iterator
            status = ATSFontFamilyIteratorCreate(kATSFontContextLocal, nil,nil,
                                                 kATSOptionFlagsUnRestrictedScope,
                                                 &theFontFamilyIterator );
            
            while (status == noErr)
            {
                // Get the next font in the iteration.
                status = ATSFontFamilyIteratorNext( theFontFamilyIterator, &theATSFontFamilyRef );
                if(status == noErr)
                {
                    CFStringRef theName = NULL;
                    ATSFontFamilyGetName(theATSFontFamilyRef, kATSOptionFlagsDefault, &theName);
                    CFArrayAppendValue(atsfontnames, theName);
                    CFRelease(theName);
                    
                }
                else if (status == kATSIterationScopeModified) // Make sure the font database hasn't changed.
                {
                    // reset the iterator
                    status = ATSFontFamilyIteratorReset (kATSFontContextLocal, nil, nil,
                                                         kATSOptionFlagsUnRestrictedScope,
                                                         &theFontFamilyIterator);
                    CFArrayRemoveAllValues(atsfontnames);
                }
            }
            ATSFontFamilyIteratorRelease(&theFontFamilyIterator);
            cfFontFamilies = atsfontnames;
#endif
        }
#elif wxOSX_USE_IPHONE
        cfFontFamilies = CopyAvailableFontFamilyNames();
#endif
        
        CFIndex count = CFArrayGetCount(cfFontFamilies);
        for(CFIndex i = 0; i < count; i++)
        {
            CFStringRef fontName = (CFStringRef)CFArrayGetValueAtIndex(cfFontFamilies, i);

            if ( encoding != wxFONTENCODING_SYSTEM || fixedWidthOnly)
            {
                wxCFRef<CTFontRef> font(CTFontCreateWithName(fontName, 12.0, NULL));
                if ( encoding != wxFONTENCODING_SYSTEM )
                {
                    CFStringEncoding fontFamiliyEncoding = CTFontGetStringEncoding(font);
                    if ( fontFamiliyEncoding != macEncoding )
                        continue;
                }
                
                if ( fixedWidthOnly )
                {
                    CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font);
                    if ( (traits & kCTFontMonoSpaceTrait) == 0 )
                        continue;
                }
                
            }
            
            wxCFStringRef cfName(wxCFRetain(fontName)) ;
            fontFamilies.Add(cfName.AsString(wxLocale::GetSystemEncoding()));
        }
        
        CFRelease(cfFontFamilies);
    }
    for ( size_t i = 0 ; i < fontFamilies.Count() ; ++i )
    {
        if ( OnFacename( fontFamilies[i] ) == false )
            break ;
    }

    return true;
}
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;
}