Embedded Fonts and Filters with Input Text in ActionScript

Problem:
We need a TextField of type TextFieldType.INPUT that has embedFonts set to true and has an inner drop shadow filter. Sounds easy enough right? The first problem is that DropShadowFilter’s don’t work correctly with TextFields created using ActionScript. The second problem is that setting embedFonts to TRUE and leaving default text empty on a TextField with type TextFieldType.INPUT causes the field not to be selectable.

Solution:
Lets tackle the DropShadowFilter first. After many failed attempts at getting filters to render correctly on TextFields the next best solution was to create a sprite that sites right behind the text field that renders the filter.

Filters for Input Text Fields

package {
	import flash.display.Sprite;
	import flash.filters.DropShadowFilter;
	import flash.text.TextField;
	import flash.text.TextFieldType;

	[SWF(pageTitle="Text Field Filter", backgroundColor="#FFFFFF", frameRate="30")]
	public class TextFieldFilter extends Sprite
	{
		public function TextFieldFilter()
		{
			var myTextField:TextField = new TextField();
			myTextField.type = TextFieldType.INPUT;
			myTextField.width = 100;
			myTextField.height = 20;
			myTextField.border = true;
			myTextField.borderColor = 0x000000;
			
			var sprite:Sprite = new Sprite();
			sprite.graphics.beginFill(0xFFFFFF, 1);
			sprite.graphics.drawRect(0, 0, myTextField.width, myTextField.height);
			sprite.filters =  [new DropShadowFilter(4, 45, 0x666666, .4, 6, 6, 1, 1, true)];
			this.addChild(sprite);
			
			this.addChild(myTextField);
		}
	}
}

Filters for Input Text Fields Sample

Next lets create an TextField with type TextFieldType.INPUT and set the embed property to TRUE. Lets set the TextFormat using the setTextFormat function of the TextField and see what happens. The text is not selectable and the input field can not be used. Instead use the defaultTextFormat property of TextField to set the format. Everything works great! My best guess at the reasoning behind this is that when the TextField class is set to type INPUT the set focus attempts to reset the format to the default format. Since the setTextFormat function only sets the initial format subsequent calls break the TextField.

Embed Input Text Issue

package {
	import flash.display.Sprite;
	import flash.text.AntiAliasType;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;

	[SWF(pageTitle="Embed Input Text", backgroundColor="#FFFFFF", frameRate="30")]
	public class EmbedInputText extends Sprite
	{
		[Embed(mimeType='application/x-font', source="assets/arial.ttf", fontName="Arial")]
		private var Arial:Class;

		public function EmbedInputText()
		{
			var myTextFormat:TextFormat = new TextFormat('Arial', 12, 0x000000);
			
			var myTextField:TextField = new TextField();
			myTextField.x = 3;
			myTextField.y = 1;
			myTextField.text = "";  //<---SET TEXT HERE (*CURSOR FIX*)
			myTextField.type = TextFieldType.INPUT;
			myTextField.embedFonts = true;
			myTextField.antiAliasType = AntiAliasType.ADVANCED;
			myTextField.width = 100;
			myTextField.height = 20;
			myTextField.border = true;
			myTextField.borderColor = 0x000000;
			myTextField.selectable = true;
			//myTextField.text = "";  //<---THIS PREVENTS THE CURSOR FROM WORKING (*CURSOR ISSUE*)
			
			//myTextField.setTextFormat(myTextFormat);  //<---THIS WILL NOT WORK (*EMBED ISSUE*)
			myTextField.defaultTextFormat  = myTextFormat;  //<---THIS DOES WORK (*EMBED FIX*)
			this.addChild(myTextField);

		}
	}
}

Comment out the FIX lines above and un-comment the ISSUE lines if you would like to see the fail cases.

Embed Input Text Sample

Cursor Issue:
Another interesting quirk. If you set the default text to an empty string AFTER setting the TextField properties when you initially click the input box the cursor is not displayed. The order of operations for setting properties of TextFields in ActionScript is VERY important.

Resources:
Flash Voodoo link
John Blanco’s RIA Developer’s Corner link
Adobe Livedocs DropShadowFilter link
Adobe Livedocs TextField link

Skimmer

“A lifestreaming thing that lets you see it all in one place”

Skimmer. The next Adobe AIR app and the hard work of many individuals over the past 6 months. It has been amazing to see this application turn from design into reality. This is a summary of the technologies used and some of the lessons learned throughout the development of Skimmer:

Skimmer

Skimmer

The first decision was easy. Use an MVC framework, more specifically PureMVC. This application was estimated in the thousands and having a backbone was very important. We spent the extra time upfront developing a solid structure which ended up helping out immensely when it came to bug fix and adding new features. Creating new views became a snap when the data providers that accessed third party API’s were completed.

The second major decision was to use a SQLite database to store content locally. This allowed for fast filtering of data and pre-processing of information. It also greatly improved the load time of the application since we only needed to gather new information.

Thirdly, we decided to use image caching for all of the commonly used images to improve load times. This increased the application start up and allows for fluid transitions between images in slide shows. By extending a bulk loader class Skimmer is able to first check the local cache before making any requests to the internet for images.

One of the major challenge was working with the third party API’s. The API’s for Flickr, YouTube, Twitter, TwitPic, Facebook and Blogger had varying levels of documentation and support. Flickr had the most feature rich API while Facebook had the most difficult API to work with. Many of them had third party AS3 libraries to use for interfacing with the service that we used as a base.

Another challenge was in skinning the flex components. The application was not designed to look like an AIR application, which is a good thing :) This, however, did create some interesting problems along the way. We used a combination of CSS, class inheritance, overrode drawing methods, and even created some custom flex components.

You can download skimmer here:
http://www.fallon.com/skimmer

A shout out to everyone that made this happen:
AL KELLY, BRENDA FOGG, CHRIS WIGGINS, DAVID SCHWEN. EXTENDED TEAM: ANDY GUGEL, SIERRA BRAVO, ANDREW WATSON, BEN DOLMAR, BLAGVOST DACHEV, CLAYTON SMITH, JON REXEISEN, KARSTEN LUNDQUIST, KONR NESS, KRIS SZAFRANSKI, MARK SEEMANN, MANISH SHRESTHA, MATT TONAK, MICHAEL WOODS, MINH VU, ROBB THOMAS, THOMAS O’NEILL.

Feel free to post any comments or questions you have about Skimmer.

http://mashable.com/2009/03/24/skimmer/

How to Fix Fuzzy Pixels in Flex

What are fuzzy pixels? Semi-transparent lines that appear on the edges of your Sprites that make them appear fuzzy or blurry. This is the result of positioning a custom drawn Sprite (using the graphics property) on non-whole number pixels (for example myObject.x = 1.5).

Your probably wondering why anyone would set a Sprite to an decimal number of pixels? Well, most of the time this occurs when the positioning is based off of a mathematical equation. For example: myObject.x = this.width / 2. This would produce 50.5 if the width of the container is 101. One of the biggest problems with this is that the fuzzy pixel problem has a waterfall effect. Everything contained within that sprite placed at a decimal number position will have semi-transparent edges. Another reason would be designers that set positioning of items to half pixels in Photoshop and attempting to reproduce the design pixel perfect in Flex.

Here is a zoomed in picture of what fuzzy pixels look like. The first and second squares are drawn using the same drawing function. One is placed on an even pixel and the other at a decimal number.

Fuzzy Pixels (Semi-Transparent Lines)

Fuzzy Pixels (Semi-Transparent Lines)

Code that produces fuzzy pixels:

private var fuzzySquare:Sprite;
private var square:Sprite;

private var squareContainer:Sprite;

public function draw():void
{
	squareContainer = new Sprite();
	squareContainer.x = 1;
	squareContainer.y = 1;

	square = new Sprite();
	square.x = 0;
	square.y = 0;
	square.graphics.clear();
	square.graphics.beginFill(0x0000FF);
	square.graphics.drawRect(0,0,30,20);
	square.graphics.endFill();
	squareContainer.addChild(square);
	
	fuzzySquare = new Sprite();
	fuzzySquare.x = square.x + square.width + 3.5;
	fuzzySquare.y = 0;
	fuzzySquare.graphics.clear();
	fuzzySquare.graphics.beginFill(0x0000FF);
	fuzzySquare.graphics.drawRect(0,0,30,20);
	fuzzySquare.graphics.endFill();
	squareContainer.addChild(fuzzySquare);

	container.addChild(squareContainer);
}

Solutions:
Use Math.floor or Math.ceil on all mathematical calculations relating to the positioning of Sprites drawn with the graphics function.

or

Rather than draw out the Sprite using graphics you could convert your sprites to images, embed them, and position them on the stage. This is the best approach when tweening is necessary requiring the object to look crisp at all times.

Note: I’ve seen this occur on odd number pixels as well but that is most likely the result of a greater positioning problem. This generally only occurs in highly nested display objects.

Registration Open for MN.swf Camp 2009

MN.swf Camp presented by Flashbelt

MN.swf Camp presented by Flashbelt

Who Should Attend?
Anyone interested in Flash, Flex, ActionScript or Adobe AIR.

What is MN.swf Camp?
A one-day event focused on connecting the local developer community and providing education on Flash Platform technologies. All for only $40!

When is it?
Monday, April 6, 2009 from 9:00am – 5:00pm

How do I register?
Go to http://mnswf.com/camp/ and register today!

Where will it be?
Minneapolis Central Library, 300 Nicollet Mall, Minneapolis, MN 55401 (Google Maps)

Speakers:
Jason Grey, Brad Bollinger, Chris Black, Nate Pacyga, Danny Patterson, Scott Langeberg, Wade Arnold, Jonathan Doklovic and Dustin Tauer