http://www.erasetotheleft.com/ RSS Feed 2010-01-16T08:00:00Z Llew Mason mailto:llewmason@yahoo.com tag:www.erasetotheleft.com,2010-01-16:/post/custom-iphone-fonts/ Custom iPhone Fonts 2010-01-16T08:00:00Z 2010-01-16T08:00:00Z <p><strong>Update</strong> 2010.03.08: Apple fixed this in the upcoming 3.2 SDK update. You can supply a list of custom fonts for the key <em>UIAppFonts</em> in the Info.plist file and they'll be loaded from the application bundle and made available for use in your application.</p> <hr/> <p>The iPhone SDK (as of version 3.1.2) doesn't provide any easy way to load custom fonts.</p> <p>Here's a function that will load all .ttf fonts included in your application bundle and make them available for use in your application. Unlike some other solutions I've seen (<a href="http://github.com/zynga/FontLabel">FontLabel</a> for example), fonts loaded in this manner can be used just like built-in fonts. i.e., [UIFont fontWithName: size:] simply works as usual.</p> <pre><code>#import &lt;dlfcn.h&gt; void loadFonts() { NSString* frameworkName = @"com.apple.GraphicsServices"; NSBundle* frameworkBundle = [NSBundle bundleWithIdentifier:frameworkName]; if (frameworkBundle) { const char* frameworkPath = [[frameworkBundle executablePath] UTF8String]; if (frameworkPath) { void* graphicsServices = dlopen(frameworkPath, RTLD_NOLOAD | RTLD_LAZY); if (graphicsServices) { BOOL (*GSFontAddFromFile)(const char*) = dlsym(graphicsServices, "GSFontAddFromFile"); if (GSFontAddFromFile) { NSArray* files = [[NSBundle mainBundle] pathsForResourcesOfType:@"ttf" inDirectory:nil]; for (NSString* fontFile in files) GSFontAddFromFile([fontFile UTF8String]); } } } } } </code></pre> <p>Although this code is pretty safe and will likely continue to work through iPhone OS updates, it makes use of APIs that Apple might consider 'private'. Caveat emptor.</p> tag:www.erasetotheleft.com,2009-08-25:/post/best-dog-ever/ Best Dog Ever 2009-08-25T07:00:00Z 2009-08-25T07:00:00Z <p>Reese <br> Born: ? <br> Died: Tuesday, August 25, 2009</p> <p><img src="/images/reese.png" alt="Reese" title="Reese"/></p> tag:www.erasetotheleft.com,2009-07-12:/post/coldplay/ Coldplay 2009-07-12T07:00:00Z 2009-07-12T07:00:00Z <p>The Gorge Amphitheater. 18th row from the stage. Dead center. Simply Awesome.</p> <p>The 2.5 hour drive to the middle of nowhere coupled with the one hour nightmare of un-parking after the show was completely worth it. Got to bed at 3am.</p> <p>As an added bonus <a href="http://www.amazon.com/Amadou-%26-Mariam/e/B000APLN5Q?tag=llewmason-20">Amadou and Mariam</a> was one of the openers. African pop at its best.</p> <p>As you can see, the new iPhone 3GS camera is a big improvement over the the 3G.</p> <p><img src="/images/coldplay-gorge.png" alt="Coldplay at the Gorge" title="Coldplay at the Gorge"/></p> tag:www.erasetotheleft.com,2009-04-03:/post/judith/ Judith 2009-04-03T07:00:00Z 2009-04-03T07:00:00Z <p>Mainstream game development seems to be somewhat lost. Successful game IP has become a huge cornerstone of the industry, and it spawns never-ending sequels, ports and spinoffs. The continuing quest for photo-realism has driven game development for the past 20+ years, but the end is in sight. Realistic physics and AI are following immediately behind photo-realism as drivers. Gaming as an artistic medium has suffered as a result. Few games tell a compelling story or generate real emotional responses. Very few games have risen to the level of art. Movies and novels have had more time as a medium, but where are the games worthy of being compared to movies like Blade Runner or books like Animal Farm?</p> <p><img src="/images/judith.png" alt="Judith" title="Judith"/></p> <p>In contrast, independent game development has come a long way over the past few years. The tools game developers use have improved significantly, and many are available free or at relatively low cost. Wheels don't need to be reinvented - game creators can concentrate on their ideas more and their code less. Simple games can be developed in hours in some cases, provided they don't need significant media assets. The independent game development community really is creating games for artistic sake, without regard for financial reward.</p> <p>This post was motivated by playing just such an indie game. <a href="http://distractionware.com/">Terry Cavanagh</a> and <a href="http://www.increpare.com/">Stephen Lavelle</a> just released a new game entitled Judith. It's an interesting 20 minute diversion built on a Wolfenstein-type engine. It's a short story about control told from two different narrative viewpoints separated in time, but not in space. Its 8-bit graphics and sound generated more real emotion than I've felt in a long time playing anything. Of course it's not Blade Runner or Animal Farm, but it is an honest step towards art in games.</p> <p>It's available for download <a href="http://distractionware.com/blog/?p=759">here</a> with Windows, Mac OS X and Linux binaries.</p> tag:www.erasetotheleft.com,2009-01-25:/post/hiding-the-iphone-status-bar/ Hiding the iPhone Status Bar 2009-01-25T08:00:00Z 2009-01-25T08:00:00Z <p><strong>Update</strong> 2009.06.17: Apple fixed this in the 3.0 SDK update. XCode now lists all of the iPhone specific <em>Info.plist</em> entries in the drop down for the key column. <em>Status bar is initially hidden</em> is the label for the <em>UIStatusBarHidden</em> key I describe below.</p> <hr/> <p>The iPhone status bar is the bar at the top that shows the carrier signal strength, time and battery indicator. Sometimes you want to remove this bar to get some extra real estate. Both code and configuration methods for controlling the status bar are well documented, but in the latter case, while what to change is obvious, how to change it isn't.</p> <p>For configuring your iPhone application to hide the status bar, you need an entry in the Info.plist file. The entry you need to add has a key of <em>UIStatusBarHidden</em> and a value of true. The important thing is that it needs to be a boolean attribute. There are two ways to create an appropriate entry.</p> <p>First method: You can edit your Info.plist file as a text file (by right clicking on the <em>Info.plist</em> file and choosing <em>Open As > Plain Text File</em>), and add the following entry:</p> <pre><code>&lt;key&gt;UIStatusBarHidden&lt;/key&gt; &lt;true/&gt; </code></pre> <p>Second method: Add an attribute in the XCode property list editor. It defaults to string types for new attributes. To change the attribute from the default string to a boolean right click the row for the attribute and choose <em>Value Type > Boolean</em>. Make sure you don't have a pre-defined key selected from the drop-down as it won't let you change the value type for those pre-defined keys. Also, make sure you aren't actively editing the text field, otherwise you'll get the wrong contextual menu popping up. This would be easier if the property list editor in XCode simply had another column for value type with a drop down, which is exactly how the Mac OS X property list editor works. They should've simply used that interface instead of coming up with a different interface for the XCode property list editor.</p> <p>For completeness, you can hide the status bar via code by calling setStatusBarHidden:(BOOL)hidden animated:(BOOL)animated on UIApplication. The most logical place to call this is from within your UIApplicationDelegate's implementation of applicationDidFinishLaunching:.</p> tag:www.erasetotheleft.com,2007-11-02:/post/the-hives/ The Hives 2007-11-02T07:00:00Z 2007-11-02T07:00:00Z <p>Last all-hands meeting we got Hell's Belles, a somewhat dubious all girl AC/DC tribute band. Three quarters of the audience probably wasn't even born when most of those songs were originally released. To make up for that, and put Amazon back on the officially cool employer list, we had The Hives live at our all-hands meeting today.</p> <p>Possibly the worst cell phone picture ever. My BlackBerry is great for reading email and lousy for taking photos. I'm looking forward to their new album (releases November 13th). Buy it DRM free from the <a href="http://www.amazon.com/dp/B000XU8I5G?tag=llewmason-20">Amazon.com MP3 store</a>.</p> <p><img src="/images/thehives.jpg" alt="The Hives" title="The Hives"/></p> tag:www.erasetotheleft.com,2005-04-24:/post/mac-os-x-key-bindings/ Mac OS X Key Bindings 2005-04-24T07:00:00Z 2005-04-24T07:00:00Z <p>I recently wanted to change some key bindings on Mac OS X. After spending a lot of time searching I found the information that I needed. However, the information was spread across several different sites. This article aims to collect all of the information that I found in a single document.</p> <p>Mac OS X allows for some powerful control over key bindings. The method I describe below allows you to modify the key binding behavior for every program that uses the standard Cocoa AppKit text edit objects.</p> <p>The default key bindings are stored in:</p> <pre><code>/System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict </code></pre> <p>Unfortunately, this file is XML and is very painful to read. You shouldn't touch this file anyway, and you should make your modifications by creating the file:</p> <pre><code>/Users/USERNAME/Library/KeyBindings/DefaultKeyBinding.dict </code></pre> <p>where USERNAME is the name of your user account. If the KeyBindings directory doesn't exist then you should create it. Note that the file name differs between the system default (StandardKeyBinding.dict) and the user override (DefaultKeyBinding.dict). The non-XML file format is basically key / action pairs:</p> <pre><code>/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ { "KEY1" = "ACTION1"; /* Bind KEY1 to ACTION1 */ "KEY2" = "ACTION2"; /* Bind KEY2 to ACTION2 */ ... } </code></pre> <p>An example is shown below:</p> <pre><code>/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ { "^f" = "moveWordForward:"; /* Ctrl-f = next word */ "^b" = "moveWordBackward:"; /* Ctrl-b = previous word */ "^v" = "pageUp:"; /* Ctrl-v = page up */ "\UF729" = "moveToBeginningOfLine:"; /* Home = start of line */ "^\UF729" = "moveToBeginningOfDocument:"; /* Ctrl-Home = start of doc */ } </code></pre> <p>A key is defined either as a printable key character (e.g., "a"), or a non-printable key character in either octal (e.g, "\177" for delete) or Unicode (e.g., "\UF700" for up arrow) encoding. The key can be preceded by one or more key 'modifiers':</p> <h4>Key Modifiers<p></h4> <pre><code> ^ : Ctrl $ : Shift ~ : Option (Alt) @ : Command (Apple) # : Numeric Keypad </code></pre> <p>For example, Control-Shift-Home would be "^$\UF729", and Command-a would be "@a". I've had some issues with the ordering of these key modifiers on OS X 10.5 Leopard. For example, "$^\UF703" (Ctrl-Shift Right Arrow) doesn't work, but "^$\UF703" does. If you are combining multiple modifiers and it doesn't work, try reordering them.</p> <p>A list of the most common non-printable key codes is shown below. A complete list can be found in the NSEvent.h header file.</p> <h4>Non-Printable Key Codes<p></h4> <pre><code>Up Arrow: \UF700 Backspace: \U0008 F1: \UF704 Down Arrow: \UF701 Tab: \U0009 F2: \UF705 Left Arrow: \UF702 Escape: \U001B F3: \UF706 Right Arrow: \UF703 Enter: \U000A ... Insert: \UF727 Page Up: \UF72C Delete: \UF728 Page Down: \UF72D Home: \UF729 Print Screen: \UF72E End: \UF72B Scroll Lock: \UF72F Break: \UF732 Pause: \UF730 SysReq: \UF731 Menu: \UF735 Help: \UF746 </code></pre> <p>An action is simply a specific string denoting the action. A list of the most common supported actions is shown below. Note the colon at the end of each action. This is required.</p> <h4>Supported Actions<p></h4> <pre><code>alignCenter: newDocument: alignJustified: openDocument: alignLeft: orderBack: alignRight: orderFront: breakUndoCoalescing orderFrontLinkPanel: cancelOperation: orderFrontListPanel: capitalizeWord: orderFrontSpacingPanel: center orderFrontTablePanel: centerSelectionInVisibleArea: outline: changeCaseOfLetter: pageDown: checkSpelling: pageUp: clearRecentDocuments: paste: complete: pasteAsPlainText: copy: pasteAsRichText: copyFont: pasteFont: copyRuler: pasteRuler: cut: performClose: delete: performMiniaturize: deleteBackward: performZoom: deleteBackwardByDecomposingPreviousCharacter: printDocument: deleteForward: raiseBaseline: deleteToBeginningOfLine: revertDocumentToSaved: deleteToBeginningOfParagraph: runPageLayout: deleteToEndOfLine: saveAllDocuments: deleteToEndOfParagraph: saveDocument: deleteToMark: saveDocumentAs: deleteWordBackward: saveDocumentTo: deleteWordForward: scrollLineDown: hide: scrollLineUp: ignoreSpelling: scrollPageDown: indent: scrollPageUp: insertBacktab: selectAll: insertContainerBreak: selectLine: insertLineBreak: selectParagraph: insertNewline: selectToMark: insertNewlineIgnoringFieldEditor: selectWord: insertParagraphSeparator: setMark: insertTab: showContextHelp: insertTabIgnoringFieldEditor: showGuessPanel: insertText: startSpeaking: loosenKerning: stopSpeaking: lowerBaseline: subscript: lowercaseWord: superscript: moveBackward: swapWithMark: moveBackwardAndModifySelection: terminate: moveDown: tightenKerning: moveDownAndModifySelection: toggleBaseWritingDirection: moveForward: toggleContinuousSpellChecking: moveForwardAndModifySelection: toggleRuler: moveLeft: transpose: moveLeftAndModifySelection: transposeWords: moveRight: turnOffKerning: moveRightAndModifySelection: turnOffLigatures: moveToBeginningOfDocument: underline: moveToBeginningOfDocumentAndModifySelection: unscript: moveToBeginningOfLine: uppercaseWord: moveToBeginningOfLineAndModifySelection: useAllLigatures: moveToBeginningOfParagraph: useStandardKerning: moveToEndOfDocument: useStandardLigatures: moveToEndOfDocumentAndModifySelection: yank: moveToEndOfLineAndModifySelection: moveToEndOfLine: moveToEndOfParagraph: moveUp: moveUpAndModifySelection: moveWordBackward: moveWordBackwardAndModifySelection: moveWordForward: moveWordForwardAndModifySelection: moveWordLeft: moveWordLeftAndModifySelection: moveWordRight: moveWordRightAndModifySelection: </code></pre> <p>There are two other variants of entries that allow you to do multi-key bindings and to bind a key to a sequence of actions.</p> <pre><code>/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ { /* Bind KEY1 to ACTION1 and ACTION2 */ "KEY1" = ("ACTION1", "ACTION2", ...); /* Multi-key bindings */ "KEY1" = { /* Bind KEY1 followed by KEY2 to ACTION1 */ "KEY2" = "ACTION1"; /* Bind KEY1 followed by KEY3 to ACTION2 */ "KEY3" = "ACTION2"; ... }; ... } </code></pre> <p>An example is shown below:</p> <pre><code>/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ { /* An example of binding a sequence of actions to a single key. Bind Control-Shift-Home to select the region from the cursor to the beginning of the line. Windows-style Control-Shift-Home. */ "$\UF729" = ("setMark:","moveToBeginningOfLine:","selectToMark:"); /* An example of binding a sequence of keys to an action. Bind Control-x Control-s to save. Emacs style C-x C-s. */ "^x" = { "^s" = "save:"; } } </code></pre> <p><p></p> <h4>Examples</h4> <p>An example key binding file for partial Windows emulation.</p> <pre><code>/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ { "^\010" = "deleteWordBackward:"; "\UF729" = "moveToBeginningOfLine:"; "^\UF729" = "moveToBeginningOfDocument:"; "$\UF729" = "moveToBeginningOfLineAndModifySelection:"; "^$\UF729" = "moveToBeginningOfDocumentAndModifySelection:"; "\UF72B" = "moveToEndOfLine:"; "^\UF72B" = "moveToEndOfDocument:"; "$\UF72B" = "moveToEndOfLineAndModifySelection:"; "^$\UF72B" = "moveToEndOfDocumentAndModifySelection:"; "^\UF702" = "moveWordLeft:"; "^\UF703" = "moveWordRight:"; "\UF72C" = "pageUp:"; "\UF72D" = "pageDown:"; "^z" = "undo:"; "$\UF728" = "cut:"; "$\UF746" = "paste:"; "^\UF746" = "copy:"; "$\UF700" = "moveUpAndModifySelection:"; "$\UF701" = "moveDownAndModifySelection:"; "$\UF702" = "moveLeftAndModifySelection:"; "$\UF703" = "moveRightAndModifySelection:"; "^$\UF702" = "moveWordLeftAndModifySelection:"; "^$\UF703" = "moveWordRightAndModifySelection:"; } </code></pre> <p>An example key binding file for partial Emacs emulation.</p> <pre><code>/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ /* The original bindings are from Mike Ferris of lorax.com as shipped * with his TextExtras package. They were further modified by Mishka Gorodnitzky * (misaka@pobox.com), Patrick Linskey, and Llew Mason. */ { "~f" = "moveWordForward:"; /* M-f */ "~b" = "moveWordBackward:"; /* M-b */ "~&lt;" = "moveToBeginningOfDocument:"; /* M-&lt; */ "~&gt;" = "moveToEndOfDocument:"; /* M-&gt; */ "~v" = "pageUp:"; /* M-v */ "^v" = "pageDown:"; /* C-v */ "~d" = "deleteWordForward:"; /* M-d */ "~^h" = "deleteWordBackward:"; /* M-C-h */ "~\010" = "deleteWordBackward:"; /* M-backspace */ "~\177" = "deleteWordBackward:"; /* M-delete */ "~\UF728" = "deleteWordForward:"; /* delete */ "\UF729" = "moveToBeginningOfDocument:"; /* home */ "\UF72B" = "moveToEndOfDocument:"; /* end */ "@\UF729" = "moveToBeginningOfParagraph:"; /* A-home */ "@\UF72B" = "moveToEndOfParagraph:"; /* A-end */ "@\UF700" = "moveToBeginningOfDocument:"; /* A-up */ "@\UF701" = "moveToEndOfDocument:"; /* A-down */ "^\UF700" = "pageUp:"; /* C-up */ "^\UF701" = "pageDown:"; /* C-down */ "\UF72C" = "pageUp:"; /* page-up */ "\UF72D" = "pageDown:"; /* page-down */ "^/" = "undo:"; /* C-/ */ "~c" = "capitalizeWord:"; /* M-c */ "~u" = "uppercaseWord:"; /* M-u */ "~l" = "lowercaseWord:"; /* M-l */ "^t" = "transpose:"; /* C-t */ "~t" = "transposeWords:"; /* M-t */ "~/" = "complete:"; /* M-/ */ "^g" = "_cancelKey:"; /* C-g */ "^a" = "moveToBeginningOfLine:"; /* C-a */ "^e" = "moveToEndOfLine:"; /* C-e */ "^x" = { "^x" = "swapWithMark:"; /* C-x C-x */ "^m" = "selectToMark:"; /* C-x C-m */ "^s" = "save:"; /* C-x C-s */ "^w" = "saveAs:"; /* C-x C-w */ "k" = "performClose:"; /* C-x C-k */ }; /* Mark-point stuff (Emacs-style mark and point bindings are * implemented but not bound by default. In the text system the * mark and point are ranges, not just locations. The "point" is * the selected range.) */ "^@" = "setMark:"; /* C-@ */ "^ " = "setMark:"; /* C-space */ "^w" = "deleteToMark:"; /* C-w */ /* Mac Style F1-F5 bindings */ "\UF704" = "undo:"; /* F1 */ "\UF705" = "cut:"; /* F2 */ "\UF706" = "copy:"; /* F3 */ "\UF707" = "paste:"; /* F4 */ "\UF708" = "_cancelKey:"; /* F5 */ } </code></pre> <p><p></p> <h4>References</h4> <p><a href="http://hcs.harvard.edu/~jrus/Site/cocoa-text.html">Customizing the Cocoa Text System</a> by Jacob Rus<br> <a href="http://macromates.com/blog/archives/2005/07/05/key-bindings-for-switchers/">TextMate Blog - Key bindings for switchers</a><br> <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/TextDefaultsBindings/TextDefaultsBindings.html">Apple Documentation - Text Defaults And Bindings</a><br> <a href="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/index.html">Apple Documentation - NSResponder supported actions</a></p>