Author Archive for Thomas

06
Jul
11

Get Network Solutions to point at an S3 instance, even with a naked domain

Wow. First off, Amazon Web Services just got really cheap. Cheap as in free – most of the time. I won’t go into detail, because, well, this is the web after all and details are so very fluid, but you should check it out.

So, I set up a static site (for now, anyway) on S3 (Simple Storage Service – I didn’t know that until recently) and a virtual machine in EC2 (Elastic Compute Cloud – didn’t know that one, either). I have a domain through Network Solutions, and I couldn’t for the life of me figure out how to point a naked domain, e.g. http://thomasqbrady.com – without the www subdomain, to the S3 instance without domain-masking.

Domain-masking, if you didn’t know, is a fancy product name that Network Solutions uses (I think the term has real meaning in other uses) for a frameset on your page. The top frame is a page on Network Solutions’ server somewhere with a fixed IP. The bottom frame is your site, wherever that might actually be hosted. That way you get an A record DNS name (their fixed-IP server) with your domain name, but you get to point wherever you like. Normally, you have to have an IP address for an A record. Amazon’s EC2 and S3 only give you DNS names (URLs), unless you pay extra.

You can set up on Network Solutions a domain forward (which will imediately redirect your users to your actual URL) instead of a domain mask, but then your users will see your ugly S3/EC2 domain names.

You might be thinking, “Just use a CNAME, dummie!”

Rude.

CNAMEs are great. I can use a CNAME to point any subdomain to a URL. For instance, I’m pointing projects.thomasqbrady.com to a Redmine instance on the EC2 server. I’m also pointing http://www.thomasqbrady.com to the S3 instance that way. If I didn’t care about the naked domain (and, realistically, it’s not that big a deal), then I could just be done with that. CNAMEs to the rescue.

But I would lose sleep over the stupid naked domain issue.

So here’s how I did it

It took me hours of tinkering to think of this. Many of you might have known right away. But I never saw this documented anywhere or found anyone else saying this worked. But it’s currently working for me.

This setup works on Network Solutions. It might work elsewhere, but that’s the only place I’ve tried.

  1. Setup domain-forwarding, forwarding your top-level domain (thomasqbrady.com in my case) to the www subdomain (www.thomasqbrady.com in my case), but without the domain-masking.
  2. Wait a bit for this to take effect.
  3. When it has, edit advanced DNS settings.
  4. Delete your A records for www and *, but leave your @ record.
  5. Now create your CNAME records for www to point at your S3 instance.
  6. You’re now forwarding from the naked domain http://%5BYOUR DOMAIN HERE] to the subdomain http://www.%5BYOUR DOMAIN HERE], which is a CNAME mask for your S3 instance, [BUCKET NAME].s3-website-us-east-1.amazonaws.com
Advertisements
18
Feb
10

BitmapData.draw & Matrix – how to copy a section out of the middle of an image

Okay, if you google this, you’ll find TONS of people frustrated with the BitmapData class’s draw method. The livedocs are pretty vague here. They don’t really tell you how to use the matrix variable you can pass draw, and they kinda make it sound like the clipRect rectangle would let you arbitrarily cut out any size and shape from the drawable source. That’s almost true. What they don’t tell you is that the section you cut out will remain at the x/y coordinates from which you cut it.

So, let’s say you have a 100×100 image, and you want a copy of the section from 10/20 to 20/30. You might think it would be this easy:

var bmpData:BitmapData = new BitmapData(10,10);// a new 10x10 image
var rect:Rectangle = new Rectangle(10,20,10,10);
bmpData.draw(drawableItem,null,null,null,rect);

Truth is, it’s not much harder, but that bit of code will not give you what you want. The bit you grabbed from 10/20 to 20/30 will remain at those coordinates in your output, and since you only made a 10×10 image, it will be empty.

Here’s the code you want:

var bmpData:BitmapData = new BitmapData(10,10);// a new 10x10 image
var matrix:Matrix = new Matrix();
matrix.translate(-10,-20);
var rect:Rectangle = new Rectangle(10,20,10,10);
bmpData.draw(drawableItem,matrix,null,null,rect);

Your clipRect, there, will take the section you want, and the matrix transformation will translate it back to 0/0.

05
Oct
09

Flash Debug Player Log Viewer

Ug. Web development. Yes, we’ve come a long way, and we now have tools like Firebug (especially giving props to the embedded version) and De MonsterDebugger (DM).

But DM requires you to include a SWC in your SWF (at least for the cool features), which you can’t do if you’re trying to see the trace output of someone else’s file (and I’m talking about when you should be doing this – when it’s appropriate).

Also, DM suffers from a major problem that most trace log viewers do: they don’t escape strings. The problem then, is that the display attempts to render HTML content rather than show you the code. Ack.

FlashTraceViewer iconSo I whipped up a super-simple Flash Trace Log Viewer that escapes strings, and has a few more features. FInd it at SourceForge (or binary).

Oh, and if you don’t know about the Flash Debug Player (I found out woefully late in my Flash development career), download it here (search on that page for the “content debugger” specific to your system – i.e. Intel Mac), and get instructions on how to set it up here. “What is it?” you ask. It writes trace() results out to a text file, for old-school debugging.

By the way, I don’t have an official certificate, so this is personally signed. But you now have the source, so you can build your own, after verifying the code doesn’t do anything creepy. : D

And you’ll, of course, need the AIR runtime.

22
May
09

DIY Loop Pedal

Check this out! Less than $20! I love Instructables!!!!

Instructables Loop Pedal

I put it in a $2 Rubbermaid container I got from Target. It’s pretty strong (I can stand on it), was easy to drill, the rubber lid grips the floor pretty well so it doesn’t slide around, and it’s easy to open up to replace the battery.

16
Apr
09

Flex/Flash Runtime Fonts with HTML

I’m guessing you arrived here because you did a search for “runtime fonts flex” or similar. I assume, therefore, that you know why you’re here. I got there just a couple months ago.

There’s a wealth of blog articles out there on how to dynamically load font libraries at runtime in Flex. here are just a few:
scottmorgan.com, undefined-type.com, nochump.com

What I seemed to find, though, was that these gave you one of two options: use a single font per Text component , TextArea or Label MXML component(in other words, no style control via HTML/CSS), or use the TextField AS class(which means you say “goodbye” to Design View in Flex Builder).

All I want is to be able to do this:


<VBox>
<TextField htmlText="&lt;span class='GothamBold'&gt;Gotham Bold&lt;/span&gt;&lt;span class='GothamBook'&gt;Gotham Book&lt;/span&gt;"/>
</VBox>

No dice.

So here’s how I did it.

I created a custom TextField AS class that can be called as an MXML component. It looks like this:

package com.[EMPLOYER].[CLIENT].decaf.components
{
import com.[CLIENT].services.StyleManager;

import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.text.AntiAliasType;
import flash.text.Font;
import flash.text.StyleSheet;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;

import mx.controls.Text;
import mx.controls.textClasses.TextRange;
import mx.events.FlexEvent;
import mx.utils.StringUtil;
/**
* This TextField differs from the native Text component in three important ways:
* 1. This TextField component intelligently sets the embedFonts attribute based on registered
* fonts and their ability to display all the glyps set to the htmlText attribute.
* 2. This TextField component exposes a styleSheet attribute, and by default will capture
* Decaf's dispatching of the event fired when the CSS document has loaded, and assign that
* document as its own stylesheet.
* 3. This TextField Component handles the oddly complex relationship between setting selectable
* to false, and yet maintaining link functionality with the hand cursor and navigateToURL intact.
* @author Thomas Brady
* @summary An extension of Text that includes embedded fonts, setting the stylesheet, while preserving link functionality.
* */
public class TextField extends Text
{
private var _styleSheet:StyleSheet;
private var styleMan:StyleManager;
private var _style:Boolean = false;
private var _embed:Boolean = false;

/** We subscribe to three event broadcasts in the constructor:
* 1. FlexEvent.UPDATE_COMPLETE - Our override of the native Text event. A key method.
* 2. MouseEvent.CLICK - Essential for preserving the linked HTML anchors while setting
* 3. StyleManager.dispatcher.ON_CSS_LOAD - When the StyleManager has loaded a CSS doc
* this TextField will then immediately set its stylesheet to the StyleManager's
* reference.
* selectable to false.*/
public function TextField()
{
super();
//super.textField.embedFonts = true;
StyleManager.dispatcher.addEventListener("ON_CSS_LOAD",updateCompleteHandler);
addEventListener(FlexEvent.UPDATE_COMPLETE, updateCompleteHandler);
addEventListener(MouseEvent.CLICK,onClick);
}

/** This is a native function of the Text component. By overriding it, we ensure
* that our improvements are not reset by the native method.
*/
private function updateCompleteHandler(e:Event):void {
super.textField.selectable = false;
super.textField.wordWrap = true;
super.textField.multiline = true;
super.textField.mouseWheelEnabled = false;
super.textField.autoSize = TextFieldAutoSize.LEFT;
if (_style) {
super.textField.styleSheet = StyleManager.styleSheet;
} else {
super.textField.styleSheet = null;
}
super.textField.embedFonts = _embed;
}

/*
* get the "class" from an HTML string, if one exists
*/
private function getFontClassName( str:String ):String
{
var _term:String = "class=";
var _classIdx:Number = str.indexOf( _term );
if( _classIdx > - 1 )
{
var _searchTermLength:Number =_term.length;
var _quote:String = str.slice( _classIdx + _searchTermLength, _classIdx + _searchTermLength + 1 );
var _lastQuoteIdx:uint = str.slice( _classIdx + _searchTermLength + 1, str.length ).indexOf( _quote );
var _className:String = str.slice( _classIdx + _searchTermLength + 1, _classIdx + _searchTermLength + 1 + _lastQuoteIdx );
return _className;
}
else
{
return null;
}
}

override protected function childrenCreated():void
{
super.childrenCreated();
}

/** The heart of the TextField class
* The first important action taken in this method is to strip out unneeded newline, carriage
* return, and tab characters that fowl up rendering. The method goes on to determine whether
* there is a stylesheet, whether the font called for in the HTML has been registered and
* whether the font contains all the glyphs necessary to render the HTML before setting the
* values of _style and _embed Booleans, which are used in updateCompleteHandler.
* NOTE: There is a useful debug loop in here (commented out) that can help you locate glyphs
* that are not included in the font. */
override public function set htmlText(value:String):void {
var regEx:RegExp = /[\n\t\r]/g;
value = value.replace(regEx,"");

if (StyleManager.styleSheet) {
_styleSheet = StyleManager.styleSheet;
//trace("assigned StyleSheet");
// get the classname from HTML string
var _className:String = getFontClassName( value );
//trace( "drawText > _className: " + _className );

// get the font-family from the _className
var _fontName:String = StyleManager.styleSheet.getStyle( "."+_className ).fontFamily;
//trace( "drawText > _fontName: " + _fontName );

if( _className != null && _fontName != null )
{
// create a Font reference
var _font:Font;

var _fonts:Array = Font.enumerateFonts();
for( var c:Number=0; c < _fonts.length; c++ )
{
if( _fonts[c].fontName == _fontName )
{
_font = _fonts[c];
break;
}
}

//trace("FONT:"+_font);

//DEBUG LOOP - checks for what glyph is not included

/*
for (var myIndex:uint=0;myIndex<value.length;myIndex++) {
if (!_font.hasGlyphs(value.substr(myIndex,1))) {
trace("FONT DOES NOT HAVE CHARACTER -"+value.substr(myIndex,1)+"- AT INDEX "+myIndex+" WHICH IS CHAR CODE "+value.charCodeAt(myIndex));
}
}
*/

if( _font.hasGlyphs( value ) )
{
trace("EMBEDDING FONT");
super.textField.styleSheet = StyleManager.styleSheet;
super.textField.antiAliasType = AntiAliasType.ADVANCED;
super.textField.embedFonts = true;
_embed = true;
_style = true;
}
else
{
//trace("NOT EMBEDDING FONT FOR ");
trace( "Embedded font does not contain all the necessary chars. using non-embedded version font for following block");
trace(value);
super.textField.styleSheet = _styleSheet;
_embed = false;
_style = true;
}
}
else
{
// there's no class name, so just use some default
trace("NO CLASS NAME");
super.textField.styleSheet = null;
var _tf2:TextFormat = new TextFormat( "_sans", 12 );
super.textField.defaultTextFormat = _tf2;
_embed = false;
_style = false;
}
} else {
trace("NO STYLESHEET");
}
super.htmlText = value;
}

protected function onClick(pEvent:MouseEvent):void
{
// Find the letter under our click
var index:int = textField.getCharIndexAtPoint(pEvent.localX, pEvent.localY);
if (index != -1)
{
// convert the letter to a text range so we can extract the url
var range:TextRange = new TextRange(this, false, index, index + 1);
// make sure it contains a url
if (range.url.length > 0)
{
// The normal click event strips out the 'event;' portion of the url.
// So to be consistent, let's strip it out, too.
var url:String = range.url;
var tlLink:String = String(range.htmlText);
var targetAndRemaining:String = mx.utils.StringUtil.trim(tlLink.slice(tlLink.lastIndexOf(" TARGET=")+9,tlLink.length - 1));
var target:String = targetAndRemaining.slice(0,targetAndRemaining.indexOf('"'));
/*
if (url.substr(0, 6) == 'event:')
{
url = url.substring(6);
}
*/
// Manually dispatch the link event with the url neatly included
//dispatchEvent(new TextEvent(TextEvent.LINK, false, false, url));
navigateToURL(new URLRequest(url),target);
}
}
}

[Bindable("valueCommit")]
[Inspectable(category="General", defaultValue="")]
public function set styleSheet(sh:StyleSheet):void {
_styleSheet = sh;
super.textField.styleSheet = sh;
}

}
}

Extending Text gets us all the real nuts and bolts we need for functionality and use in MXML. Text, however, does not set embedFonts to true, nor does it even expose that attribute (from its super class Label).

So right there in updateCompleteHandler, which is called any time a property of the TextField changes, we go ahead and set the embedFonts to true. In reality, you’ll probably want to do some tests before you go ahead and set that true: you’ll want to check to see that you have loaded the fonts the TextField wants to use and that the fonts you loaded have all the glyphs in your string, for instance. We also set the stylesheet.

The selectable property is also an interesting challenge. Thanks to this Flex Cookbook tip we can turn selectable off and still get anchor tags to properly link.

The stylesheet dependency introduces some interesting timing issues. I’m instantiating this class via MXML, so I can’t count on the stylesheet (the CSS doc) having loaded. Flex is going to scoop up this MXML and start rendering right away, and the first time updateCompleteHandler gets called, we’re not going to have a stylesheet. So I have a static stylesheet class that dispatches an “ON_CSS_LOAD” event, to which the TextField class listens, and fires updateCompleteHandler when it hears it. At that point, and forward, there will be an actual stylesheet.

There’s also the set styleSheet for overrides, which is inspectable, which lets you modify this variable via AS or MXML.

So what you end up with is an MXML component that you can see in design mode. You can, therefore, easily lay things out. You won’t, yet, see any embedded fonts. You’re not at runtime. You also can’t double-click the component in design view to edit the text, the way you can a Text component. That’s something I’d like to look into.

07
Apr
09

MacBook Tablet

macbook_black_200605171

Make your own MacBook Tablet

Cintiq tablets are awesome. Few things have inspired such gear-lust in me. Okay, maybe not too few, but…

I had an old Wacom 5×7 Graphire tablet lying around that I wasn’t using much anymore, and was inspired to make my own MacBook tablet with it by this Instructables article.

A few messy hours later (polycarbonate + Dremel = BIG mess) and I had a working tablet MacBook (with only 5″x7″ of the screen being tablety). If you’re now inspired, you can try my how-to article: MacBook Tablet or DIY Cintiq or Homebrew Mac Tablet