I don’t really know what I’m doing when it comes to OSX and Obj-C but I do know enough to learn more and not give up just because ‘it’s too hard’. I also know to learn with something simple, but useful and that would be shoe_font_list() which is called at Shoes init time and populates the Shoes::FONTS array for Ruby. The clang compiler complains about deprecations (from 10.5 or 10.6 time). Time to learn and update something that works.
tiny test script:
Shoes.app do para "Fonts:n" Shoes::FONTS.each {|font| para font+"n"} end
I learned OSX folks don’t write as many blog posts describing problems and solutions like the Linux folk do. So, Shoes used the older ATS C level api and the newer better thing is CoreText (CT). Note, I wasted a day digging into a hole with NSFontCollection (but I learned some Obj-C so I can’t complain). I found this bit of code and I modfified it slightly for Shoes. After much testing and horsing around, it works. I don’t about the memory management issues. FIXME: I guess, maybe.
Since shoes_font_list is small, I’ll post it here for others who may google upon it.
VALUE shoes_font_list() { INIT; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 VALUE ary = rb_ary_new(); CFBooleanRef value= kCFBooleanTrue; int vtrue[1] = {1}; CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)kCTFontCollectionRemoveDuplicatesOption, (const void **)&vtrue, 1, NULL, NULL); CTFontCollectionRef fcref = CTFontCollectionCreateFromAvailableFonts(dict); CFArrayRef arrayref = CTFontCollectionCreateMatchingFontDescriptors(fcref); CFRelease(fcref); CFIndex count = CFArrayGetCount(arrayref); CFIndex i; for (i=0; i<count; i++) { CTFontDescriptorRef fdesc =(CTFontDescriptorRef)CFArrayGetValueAtIndex(arrayref, i); CTFontRef font = CTFontCreateWithFontDescriptor(fdesc, 0., NULL); CFStringRef cfname = CTFontCopyFullName(font); static char fname[100]; CFStringGetCString(cfname, fname, sizeof(fname), kCFStringEncodingUTF8); rb_ary_push(ary, rb_str_new2(fname)); } #else ATSFontIterator fi = NULL; ATSFontRef fontRef = 0; NSMutableArray *outArray; VALUE ary = rb_ary_new(); if (noErr == ATSFontIteratorCreate(kATSFontContextLocal, nil, nil, kATSOptionFlagsUnRestrictedScope, &fi)) { while (noErr == ATSFontIteratorNext(fi, &fontRef)) { NSString *fontName; ATSFontGetName(fontRef, kATSOptionFlagsDefault, &fontName); if (fontName != NULL) rb_ary_push(ary, rb_str_new2([fontName UTF8String])); } } ATSFontIteratorRelease(&fi); #endif RELEASE; rb_funcall(ary, rb_intern("uniq!"), 0); rb_funcall(ary, rb_intern("sort!"), 0); return ary; }
shoe_load_font(filename) will be next. No, I haven’t fixed a bug users would see. I have a lot to learn about Obj-c and Cocoa and AppKit. I’ll start with something bite sized before diving into the the deep end of the pool.