GhostWire Studios - Flash/Flex UI Components Development And Consulting Services
Quality User Interface Controls For Flash Application DevelopmentAspireUI Components

Apr 09 2009

Loading embedded fonts on-demand using the uiFonts manager

Published by sunny at 1:57 pm under Aspire UI,Flash,Tips

Why Embed Fonts?
Embedding a font inside a SWF file means that the font does not need to be present on the devices the SWF file eventually plays back on. In order to ensure that text are rendered in the way the Flash application developer originally intended, it is often necessary to embed the fonts used in the application. This is especially so for fonts that are not commonly installed in the target devices. The use of embedded fonts is also mandatory for some features of the Flash Player to work, such as text rotation and transparency (pre-Flash Player version 10).


The Problem
Unfortunately, embedding fonts into the application SWF can seriously bloat the file size. It will also increase compile time significantly, wasting much development time.


The Solution
Using the uiFonts manager from Aspire UI Standard Edition, it is possible to use embedded fonts without compiling them into the main application SWF. Instead, each individual font exists in its own external SWF file which is loaded into the application on-demand during run-time. These font SWF files can be created once for each font and re-used across different applications.

This is especially helpful for applications where the use of embedded fonts is essential, such as an apparel print design or greeting card design application that offers multiple font choices.


Live Demo
The following is a live demo of the uiFonts manager in action (FontsExample.swf):

Get Adobe Flash player

  • The text displaying “The quick brown fox jumps over the lazy dog.” is slightly rotated, so it won’t show up unless it is using embedded fonts.
  • The application starts with no embedded font available for usage.
  • Clicking the “DejaVu Sans” button loads the “DejaVu_Sans.swf” file from the “assets/fonts/” folder. Once it is loaded, the embedded font will be used automatically. To load the font dynamically during run-time, uiFonts.manager.load(“DejaVu Sans”) is called – the font name is specified, not the font file name.
  • Likewise, clicking the “SanaFon” button loads “SanaFon.swf” – uiFonts.manager.load(“SanaFon”) is called.
  • A Bold version of the “SanaFon” font does not exists.


FontsExample.as
Here is the source code of the FontsExample.as class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package
{
	import com.ghostwire.ui.containers.*;
	import com.ghostwire.ui.controls.*;
	import com.ghostwire.ui.data.*;
	import com.ghostwire.ui.events.*;
	import com.ghostwire.ui.enums.*;
	import com.ghostwire.ui.managers.*;
 
	import flash.display.Sprite;
	import flash.events.*;
	import flash.system.Capabilities;
 
	public class FontsExample extends Sprite
	{
		// ** instances **
		private var displayTextA:uiText;
		private var displayTextB:uiText;
		private var progressText:uiText;
 
		public function FontsExample()
		{
			// ** make sure stage is not null **
			addEventListener(Event.ADDED_TO_STAGE,init);
		}
 
		private function init(evt:Event):void
		{
			// ** let assets preload before starting application **
			uiSkins.manager.addEventListener(Event.INIT,main);
		}
 
		private function main(evt:Event):void
		{
			// ** topLevelPane **
			var topLevelPane:uiPane = new uiPane();
			topLevelPane.padding	= 4;
			topLevelPane.setSize(stage.stageWidth,stage.stageHeight);
			addChild(topLevelPane);
 
			var titleText:uiText	= new uiText("Aspire UI Components Example");
			titleText.alignX	= ALIGN.CENTER;
			titleText.background	= {color:0x819A98,cornerRadius:12}
			titleText.padding	= "6,12";
			titleText.textStyle	= "title";
			topLevelPane.addChild(titleText);
 
			var versionText:uiText	= new uiText("Flash Player Version "+Capabilities.version);
			versionText.alignX	= ALIGN.CENTER;
			versionText.y		= topLevelPane.height - 80;
			topLevelPane.addChild(versionText);
 
			var footerText:uiText	= new uiText("© 2008-2009 GhostWire Studios")
			footerText.background	= {color:0x819A98};
			footerText.padding	= 3;
			footerText.alignX	= ALIGN.CENTER;
			footerText.fillX	= true;
			footerText.textStyle	= "footer";
			footerText.y		= topLevelPane.height - 60;
			topLevelPane.addChild(footerText);
 
			var ghostwireMark:uiImage	= new uiImage("GhostWireStudiosMark");
			ghostwireMark.alignX	= ALIGN.CENTER;
			ghostwireMark.alignY	= ALIGN.BOTTOM;
			topLevelPane.addChild(ghostwireMark);
 
			// ** display text **
			displayTextA		= new uiText();
			displayTextB		= new uiText();
 
			displayTextB.rotation = 2; // ** text will not show unless using embedded font **
 
			displayTextA.text	=
			displayTextB.text	= "The quick brown fox jumps over the lazy dog.";
 
			var txt:uiBox	= new uiBox();
			txt.vertical		= true;
			txt.alignX		= ALIGN.CENTER;
			txt.y			= 60;
			txt.addChild(displayTextA);
			txt.addChild(displayTextB);
 
			topLevelPane.addChild(txt);
			// ** end display text **
 
			// ** buttons **
			var buttons:uiBox	= new uiBox();
			buttons.alignX		= ALIGN.CENTER;
			buttons.y		= 150;
			buttons.spacing		= 20;
 
			var buttonA:uiLabelButton	= new uiLabelButton("DejaVu Sans");
			var buttonB:uiLabelButton	= new uiLabelButton("SanaFon");
 
			buttonA.fillY			= true;
			buttonB.fillY			= true;
 
			buttonA.data		= "styleA";
			buttonB.data		= "styleB";
 
			buttonA.addEventListener(MouseEvent.CLICK,on_click,false,0,true);
			buttonB.addEventListener(MouseEvent.CLICK,on_click,false,0,true);
 
			buttons.addChild(buttonA);
			buttons.addChild(buttonB);
 
			topLevelPane.addChild(buttons);
			// ** end buttons **
 
			// ** progress text **
			progressText		= new uiText();
			progressText.alignX	= ALIGN.CENTER;
			progressText.y		= 190;
			topLevelPane.addChild(progressText);
			// ** end progress text **
 
			// ** end topLevelPane **
 
			// ** create some text styles **
			uiTextStyles.manager.setStyle("styleA",{fontFamily:"DejaVu Sans",fontSize:16});
			uiTextStyles.manager.setStyle("styleB",{fontFamily:"SanaFon",fontSize:16});
			uiTextStyles.manager.setStyle("styleABold",{fontFamily:"DejaVu Sans",fontSize:16,fontWeight:"bold"});
			uiTextStyles.manager.setStyle("styleBBold",{fontFamily:"SanaFon",fontSize:16,fontWeight:"bold"});
		}
 
		/**
		apply new text style and load external font swf on demand
		*/
		private function on_click(evt:MouseEvent):void
		{
			displayTextA.textStyle = String(uiLabelButton(evt.target).data);
			displayTextB.textStyle = displayTextA.textStyle+"Bold";
			if (displayTextA.embedFonts)
			{
				// ** embedded font already loaded and in use **
				progressText.text = "";
			}
			else
			{
				// ** begin loading external font swf **
				progressText.text = "Loading...";
				uiFonts.manager.load(uiLabelButton(evt.target).text);
				uiFonts.manager.addEventListener(ProgressEvent.PROGRESS,on_loadProgress);
			}
		}
 
		/**
		tracks download progress
		*/
		private function on_loadProgress(evt:ProgressEvent):void
		{
			progressText.text = ((evt.bytesLoaded == evt.bytesTotal) ? "Total: " : "Loading: ")+evt.bytesLoaded+" bytes";
		}
	}
}
  • Lines 67-84: This is the display text for “A quick brown fox jumps over the lazy dog”. Notice that the “rotation” property of the containing box is set to 2 – the text will not show unless embedded fonts are used.
  • Lines 87-108: These are the buttons that will set the text to the text styles using the respective fonts, and initiate the loading of the external font swf files.
  • Lines 111-116: This is the text that shows the loading progress while an external font SWF file is being loaded.
  • Lines 121-124: Set some text styles to use the respective fonts.
  • Lines 130-146: Event handler when a button is clicked. Notice the “embedFonts” property is queried – this property automatically assume true/false depending on whether the embedded font is available or not.
  • Lines 151-155: Event handler for tracking the download progress of external font SWF files.
  • Notice that there is no code explicitly asking text fields to use embedded fonts (after the fonts are loaded) – this is not necessary because the uiFonts manager works together with the uiTextStyles manager to invalidate and redraw uiText instances automatically after a font is loaded.


Font SWF Files
For instructions on how to create individual font SWF files, please refer to uiFonts usage notes.


Aspire UI Components
Aspire UI is a library of Actionscript 3.0 (AS3) classes for building flexible and lightweight UI elements in Adobe Flash applications. Key features of the components include easy skinning using PNG image files, automatic tab focus ordering, CSS text styles, and layout management. This is a pure AS3 library with no dependency on the Flex framework. You may experiment with the various features by downloading a trial version.

pixelstats trackingpixel
Share or Bookmark This Post:
  • StumbleUpon
  • email
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Live
  • Yahoo! Buzz
  • Netvibes
  • NewsVine
  • Reddit
  • Slashdot
  • Technorati
  • BlinkList
  • Mixx
  • Diigo
  • Faves
  • Suggest to Techmeme via Twitter
  • Twitter

Other Posts You Might Enjoy:

           

5 responses so far

5 Responses to “Loading embedded fonts on-demand using the uiFonts manager”

  1. Rick Winscoton 09 Apr 2009 at 9:53 pm

    Embedding fonts in Flex is an attractive feature… but can be a dangerous one from a legal perspective if you haven’t done some homework. Most fonts installed on your computer, included with your OS, purchased from vendors, and etc are licensed to you and only you for the purpose of creating ‘derivative’ works… e.g. creating business cards, a poster, t-shirts, graphics for a website and are not intended for redistribution with a software application.

    There are many free fonts on the web – but keep in mind that ignorance is no defense if the ‘free’ font you downloaded turns out to be owned by someone else. Due diligence is always required. It’s always a good idea to get permission in writing where your intended purpose is disclosed in full with verbiage that establishes authorship.

    Great post by the way!

  2. Mem’son 10 Apr 2009 at 8:30 am

    I’m working on similar system. The main problem in loading embeded font in external SWF is the huge size when need CJK glyphs. But i found a solution : streaming font for load on demand needed glyphs.
    My post about this, but in French yet, sorry:
    http://memmie.lenglet.name/?p=33
    Direct link to demo:
    http://memmie.lenglet.name/documents/lab/fontstream/waterfall_demo.html

  3. sunnyon 10 Apr 2009 at 3:51 pm

    @Rick, thanks – those are very valid points you raised. I have updated the uiFonts documentation page to include a reminder that says “Before compiling fonts into SWF files, read the font EULA to see if permission to do so has been granted. If in doubt, contact the font vendor for advice before proceeding.”

    Come to think of it, Adobe should probably do it in its documentation too! :)

  4. Frode Hanssenon 17 Apr 2009 at 5:37 am

    @mems

    Embedding fonts from Flex like Lee Brimelow (http://gotoandlearn.com/play?id=102) is very nice, I just noticed a very important thing: Remember to add space if you are picking out separate Glyphs. If not the glyphs will space out very strange if you select them or apply bold / italics. Whistespace is a glyph too even if it is not visible. Sorry if this post was a bit offtopic.

    @Sunny

    Brilliant components!
    Does the font manager support the Flex way of embedding them as well using the metaData tag ?

    -F

  5. sunnyon 17 Apr 2009 at 6:21 am

    Yes, the uiFonts manager will work just as well with font swfs compiled using the Flex compiler, ie using the [Embed] metatag. In fact, that is the only way (that I know of) should you want to specify unicodeRange.

    I should probably post another entry on how the AS3 class used to compile a font swf would look like. Thanks!

    Update:
    http://ghostwire.com/blog/archives/compiling-embedded-font-swfs-with-the-flex-compiler-for-use-with-the-uifonts-manager/

Trackback URI | Comments RSS

Leave a Reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word