http://www.erasetotheleft.com/RSS Feed2010-01-16T08:00:00ZLlew Masonmailto:llewmason@yahoo.comtag:www.erasetotheleft.com,2010-01-16:/post/custom-iphone-fonts/Custom iPhone Fonts2010-01-16T08:00:00Z2010-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 <dlfcn.h>
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 Ever2009-08-25T07:00:00Z2009-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/Coldplay2009-07-12T07:00:00Z2009-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/Judith2009-04-03T07:00:00Z2009-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 Bar2009-01-25T08:00:00Z2009-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><key>UIStatusBarHidden</key>
<true/>
</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 Hives2007-11-02T07:00:00Z2007-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 Bindings2005-04-24T07:00:00Z2005-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 */
"~<" = "moveToBeginningOfDocument:"; /* M-< */
"~>" = "moveToEndOfDocument:"; /* M-> */
"~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>