The Flex framework has a great deal of functionality built into it, making it relatively easy to start building applications. All of the user interface components and layout containers greatly simplify the process of creating a new application because you can utilize all the functionality of the components without having to write all the code to make them work. As great as that is, it would be nearly useless in most cases if you couldn't customize the appearance of the components. Yet, as we’ll see in this chapter, customization of the appearance of Flex components is another built-in feature.
There are essentially two ways you can customize the appearance of components:
Apply styles.
Change skins.
Styles are settings such as color, font face, border settings, row height, and so on. These are settings that you can customize entirely programmatically both at compile time and at runtime. Styles allow you to customize a great deal of the appearance of components, yet they can go only so far. For example, if you want to change the background color of a button, you can do that using styles, but if you want to completely change the shape of a button (e.g., from a rounded rectangle to a trapezoid), you need to use a different technique in which you change the skins of the component. Skins can be graphical elements (e.g., PNG files) or programmatic elements (classes), and they allow you to not only customize the existing elements of a component, but also completely change which elements are used. Therefore, using custom skins allows you to alter the appearance of a component so completely that it is unrecognizable from its original default appearance. You can use both styles and skins at the same time (although oftentimes applying a skin will cancel out certain style settings).
In this chapter, we’ll look more closely at all the techniques you can use to customize application appearance through the use of styles and skins. We’ll also look at working with fonts, using Cascading Style Sheets (CSS), customizing an application preloader, and creating custom themes for styling.
Styles allow you to control a great many aspects of an application’s appearance, including colors, fonts, spacing, animation settings, and more. You can define and apply styles in many ways, each with its own advantages and disadvantages. These can be categorized as follows:
Because there are so many ways to apply styles, it is actually possible to apply different values for the same style to a component using different ways to apply that style. For example, you can set the color of a button component using an instance style as well as using a type selector. Because this is possible, it’s necessary for Flex to have an order of precedence for the application of styles. That order (from greatest precedence to least) is the same as the list preceding this paragraph. That means that if Flex has to decide between an instance style and a type selector, it will use the value from the instance style.
There are lots of different styles, and each style has a
required data type for its value. For example, the style used to set the font
face (fontFamily
) requires a string
value specifying the name of the font to use, yet the style used to set
the font size (fontSize
) requires a
numeric value. Behind the scenes, all styles accept values of one of
these two data types: string and number. However, for convenience, some styles accept more than
one type of value. For example, color styles should be specified using
numeric values, but you can also specify one of the color strings, such
as red or green. Those values are translated to number values behind the
scenes. Also, some styles actually require number values of 0 or 1, but
you can optionally specify a Boolean value of true
or false
. This next example sets the
dropShadowEnabled
property to
1
, but it could also use the value
true
to achieve the same
effect:
<mx:Style> VBox { backgroundColor: green; borderStyle: solid; dropShadowEnabled: 1; } </mx:Style> <mx:VBox width="200" height="200" />
Some styles allow you to specify a unit of measurement. However,
Flex ignores all units of measurement, using only the numeric portion of the value. For example,
when you specify a font size, you can also specify a unit of measurement
such as pixels or points, though the result will always be the same
regardless of what unit of measurement is specified (or if none is
specified). This allows you to use the same stylesheets for your Flex
applications that you might use with HTML applications. The following
example sets the font-size
property
of a class selector to 15px
, which is interpreted simply as 15 by
Flex:
.example { font-size: 15px }
The Flex Style Explorer allows you to see what styles are available for Flex components, and you can adjust those settings in real time and see the generated CSS to create the style settings. You can view the Flex Style Explorer at http://examples.adobe.com/flex3/consulting/styleexplorer/Flex3StyleExplorer.html.
Instance styles are the styles set for a specific component instance. You can set instance styles using MXML or ActionScript. Setting instance styles using MXML is often referred to as setting an inline style, because you simply set the value for an attribute in the component tag. Here’s an example of a button component for which we’re setting the color style:
<mx:Button label="Example" color="red" />
You can set many inline styles at the same time. Here’s the same button with additional styles set inline:
<mx:Button label="Example" color="red" borderColor="yellow" cornerRadius="10" fontStyle="italic" />
You can also set styles on an instance using ActionScript via the setStyle()
method. The setStyle()
method is defined by UIComponent
, which means that you can call the method for all (visual)
Flex components. The setStyle()
method requires two parameters: the name of the style property as a
string (e.g., color) and the value for the property. Here’s an example
that sets a button component’s color style:
button.setStyle("color", "red");
If you want to set many styles for a component, you need to call
setStyle()
for each style. Here’s an
example that sets many styles for one component:
button.setStyle("color", "red"); button.setStyle("borderColor", "yellow"); button.setStyle("cornerRadius", 10); button.setStyle("fontStyle", "italic");
If you apply styles using setStyle()
, you can change styles at runtime.
That means you can use setStyle()
to
change a style even if it was set inline. Example 8-1 sets the color
style both inline and with ActionScript. Because setStyle()
is called after the inline style
was applied, the button label appears in red rather than green.
Example 8-1. Setting a style with setStyle()
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initializeHandler(event)"> <mx:Script> <![CDATA[ private function initializeHandler(event:Event):void { button.setStyle("color", "red"); } ]]> </mx:Script> <mx:Button id="button" label="Example" color="green" /> </mx:Application>
The following shows an interactive version that demonstrates how
setStyle()
allows you to make changes
at runtime:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ private function changeColor(color: String):void { button.setStyle("color", color); } ]]> </mx:Script> <mx:Button id="button" label="Change Color" color="green" toggle="true" click="changeColor(button.selected ? 'blue' : 'red')" /> </mx:Application>
If you want to retrieve the style value for a specific instance, you can
use the getStyle()
method. The getStyle()
method
requires a parameter specifying the name of the style. The method then
returns the current value of the style. The following example retrieves
the color style value for the button and displays it:
<mx:Button id="button" label="Example" color="red" /> <mx:TextInput text="{button.getStyle('color').toString(16)}" />
The use of toString()
in the
preceding code outputs the value using a radix of 16, effectively
displaying the color in hexadecimal format.
Applying instance styles using inline style attributes is convenient. However, it has a major drawback in that it decentralizes style settings for the application, making it difficult to manage. Instead, you can use CSS to define styles for components. Although you can use CSS that gets loaded at runtime, this section deals only with CSS that is compiled into the Flex application. (We’ll look at runtime CSS in Runtime CSSˮ later in this chapter.)
CSS is a standard way for applying styles across platforms, languages, and frameworks. The syntax of CSS in Flex is identical to the syntax of CSS as it is used by HTML. For example, here’s a sample class selector for a Flex application written in CSS:
.example { color: red; }
Even though the syntax of CSS in Flex is identical to that used by HTML, some of the style properties available in HTML are not available in Flex.
When you define CSS for Flex applications, you have two basic options: external stylesheets and local style definitions. In both cases, the CSS is compiled into the Flex application, so they are functionally identical. However, there are advantages to each. External stylesheets enable you to more cleanly distinguish between layout (MXML) and style definitions (external CSS document). On the other hand, local style definitions are more convenient when you intend to use the style or styles in just one MXML file. For most applications external stylesheets are preferable.
An external stylesheet is a text file that you compile into a Flex
application by using the source
attribute of a Style
MXML tag.
The following code is an example of a Style
tag that compiles in an external
stylesheet defined in styles.css.
The styles defined in the external document are then available within
the MXML document within which the Style
tag appears.
<mx:Style source="styles.css" />
If you want to define local style selector definitions, you can
simply place the CSS between opening and closing Style
tags, as in the following
example:
<mx:Style> .example { color: red; } </mx:Style>
Whether you’re using external stylesheets or local style
definitions, you can define the same sorts of style selectors: class
selectors and type selectors. Class selector names are differentiated from type selector names because
they use a dot (.
), as in the
preceding example. A selector can define one or more styles. The
preceding example defines just one style for the selector. The following
example defines two styles for the selector
.example { color: red; font-style: italic; }
When you want to apply a class selector to a component, you must set the styleName
property of the component.
The styleName
value
should be the name of the class selector, but without the initial dot.
The following example sets the styleName
property of a button to the example
style selector:
<mx:Button label="Example" styleName="example" />
If you want to set the styleName
property of a component using
ActionScript, you can do that using standard dot syntax, as
follows:
button.styleName = "example";
The other kind of selector is called a type selector, and it automatically applies to all components of the type
that match the name of the selector. For example, you can define a type
selector called Button
, and it will
automatically get applied to all buttons:
Button { color: red; }
Type selectors work with all component types, including custom
components. That means you can define type selectors for standard Flex
components such as Button
, Application
, TileList
, and so forth, but you can also
define type selectors for custom Flex components, whether those
components are third-party components or components that you and your
team have written.
You cannot combine type and class selectors by defining class selectors that are specific to a type as you would in HTML. Flex will not throw an error in this case, but it will simply ignore the type. The following example illustrates this:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> Button.example { color: green; } Label.example { color: yellow; } </mx:Style> <mx:Button label="button" styleName="example" /> <mx:Label text="label" styleName="example" /> </mx:Application>
In this example, you might expect that the button text would
appear in green and the label text in yellow. However, both appear with
yellow text. That is because Flex ignores the type selector portion of
the selector names, and instead both selectors are defined simply as
class selectors with the same name (.green
) and the second overwriting the first.
The result is that the text for both the button and the label is
yellow.
With both type and class selectors you can use comma-delimited
lists to define the same property values for several
selectors. For example, the following sets the color
for Button
and TextInput
components:
Button, TextInput { color: red; }
You can also define properties for a selector in more than one
property grouping. For example, the following defines the color
as red
for Button
and TextInput
, but then it also sets the themeColor
for Button
:
Button, TextInput { color: red; } Button { themeColor: black; }
Type selectors always take precedence over class selectors. Example 8-2 defines a type selector and a class selector. In this case, the font style is italic because the type selector sets it. However, because the class selector defines the color as green, the button label is green rather than red.
Example 8-2. Selector precedence
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> Button { color: red; font-style: italic; } .example { color: green; } </mx:Style> <mx:Button label="Example" styleName="example" /> </mx:Application>
Neither local style definitions nor external stylesheets take
precedence inherently. If you use both in one document, you will see that the
order in which they appear in the document is what determines which
takes precedence. Let’s look at a complete example that illustrates
this. Here’s styles.css, an
external stylesheet document. It contains just one style definition, a
class selector called example
:
.example { color: red; font-style: italic; }
Example 8-3 is the MXML document that both uses this external stylesheet and has a local style definition for the same class selector. In this case, the button has a green and italicized label because the local style definition takes precedence over the external stylesheet, only because it appears after the external stylesheet included in the code.
Example 8-3. Order of style tags affects styles (part 1)
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style source="styles.css" /> <mx:Style> .example { color: green; } </mx:Style> <mx:Button label="Example" styleName="example" /> </mx:Application>
Yet, if you reverse the order of the two Style
tags, as in Example 8-4, you’ll see that the
button label is now red. This is because when properties of the same
name are defined for a selector multiple times, the last definition
overrides previous definitions. In the case of this example, the latter
definition is that which is imported into the document via the external
.css file.
Example 8-4. Order of style tags affects styles (part 2)
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
.example {
color: green;
}
</mx:Style>
<mx:Style source="styles.css" />
<mx:Button label="Example" styleName="example" />
</mx:Application>
In Flex, all style property names must be capable of being treated as
variables. For this reason, it’s necessary that all style property
names follow the naming rules for variables, meaning they must consist
of alphabetic and numeric characters. Notably, variable names cannot
contain hyphens. However, traditional CSS style property names use hyphens (e.g., font-family
), and for this reason, Flex
supports both hyphenated and camel-case style property names in CSS. (Flex converts
hyphenated style property names to the camel-case equivalent behind the
scenes.) For example, if you want to set the font name, you can use the
style property font-family
or
fontFamily
when using CSS. However,
you cannot use hyphenated style properties in ActionScript using setStyle()
or with inline
styles.
Behind the scenes, Flex converts all CSS to ActionScript
instructions that are managed by a class called mx.managers.StyleManager
. In most cases, it is not necessary to work directly with
the StyleManager
class. However, in
the event that you want to have greater runtime control over styles
applied as either class selectors or type selectors, you’ll need to work
with StyleManager
.
The StyleManager
class allows
you to access and configure existing selectors that were created via
CSS, and it allows you to add new selectors programmatically. To access an existing selector use the static method
called getStyleDeclaration()
.
The method requires a string parameter specifying the name
of the selector. The name of the selector should include the initial dot
for class selectors. The method returns an mx.styles.CSSStyleDeclaration
object
representing the selector:
var selector:CSSStyleDeclaration = StyleManager.getStyleDeclaration(".exampleSelector");
If you try to access a selector that does not exist, the Flex application will throw a runtime error.
You can use the setStyle()
method for a CSSStyleDeclaration
object to edit the styles for that object. The setStyle()
method for CSSStyleDeclaration
is identical to the method
of the same name for UIComponent
. You
pass it the name of the style and the new value, as in the following
example:
selector.setStyle("color", "red");
If you want to add a new selector at runtime that wasn’t defined
at compile time, you can do so by constructing a new CSSStyleDeclaration
object and then adding it
to the StyleManager
using the
setStyleDeclaration()
method. The
setStyleDeclaration()
method allows
you to specify the name of the selector (specifying null
will cause the StyleManager
to use the name of the selector
from the CSSStyleDeclaration
object),
the CSSStyleDeclaration
object, and a
Boolean value indicating whether to immediately update the styles for
affected components:
var selector:CSSStyleDeclaration = new CSSStyleDeclaration(".newSelector"); StyleManager.setStyleDeclaration(null, selector, true);
Setting a style declaration is a computationally expensive
operation. If you are going to set more than one style declaration at a
time, it is best to set the third parameter of the setStyleDeclaration()
method to false
for all but the last method call:
StyleManager.setStyleDeclaration(".newSelector1", selector1, false); StyleManager.setStyleDeclaration(".newSelector2", selector2, false); StyleManager.setStyleDeclaration(".newSelector3", selector3, false); StyleManager.setStyleDeclaration(".newSelector4", selector4, true);
You should be careful when using setStyleDeclaration()
that you don’t
mistakenly overwrite an existing selector. Most component types already
have type selectors defined in the defaults.css document (found in the default
theme used by Flex, as discussed in Themesˮ later in
this chapter) that is compiled into Flex applications by default. That
means that even if you didn’t define a Button
type selector, your Flex application is
probably using one that it compiled in from defaults.css. Therefore, if you replace the
Button
type selector with a call to
setStyleDeclaration()
, you will lose
all the style settings that buttons have by default if you haven’t
explicitly given values to those styles in your new selector. The better
option in most cases is to get a reference to the existing CSSStyleDefinition
object and edit the style
values for that object using setStyle()
.
You can apply global styles using the global
selector. You can set the global
selector in external stylesheets, in local style definitions, or by
using StyleManager
. Global styles
always have the lowest precedence. That means that a global style will be applied only if
it’s not overridden by a higher-priority setting such as a type
selector, a class selector, or an instance style. Example 8-5 uses a global
selector along with a class selector.
In this example, the first button is green and italic, and
the second button uses just the global style settings.
Example 8-5. Using a global selector with a class selector
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"> <mx:Style> global { color: red; font-style: italic; } .example { color: green } </mx:Style> <mx:Button label="Example 1" styleName="example" /> <mx:Button label="Example 2" /> </mx:Application>
Style precedence can be a little confusing at first because there are simply so many ways to set styles. For that reason, we’ll now summarize the precedence. From highest precedence to lowest, here’s the list:
When you want to customize the font used by components within your Flex application, you’ll need to know the specifics of how to work with font outlines. The first important thing to understand in regard to this topic is how Flex differentiates types of fonts. In terms of how Flex deals with fonts, there are three types of fonts:
These are the fonts that are installed on the user’s system. Just as an HTML page can display text using a font installed on the user’s system, so too can Flex applications.
There are three device fonts: _sans
, _serif
, and _typewriter
, which resolve to the most
similar system font on the user’s computer.
Flex applications allow you to embed font outlines within the .swf file, so you can guarantee that all users will see the same font even if they don’t have it installed on their system.
When you use system fonts, you add no additional file size to the
Flex application by embedding fonts. You can specify system fonts
simply by specifying the name of the system font to use for the
fontFamily
(or font-family
) style, as in the following
example:
font-family: Verdana;
The problem with system fonts is that the user must have the
font. Otherwise, the text will render using the default system font.
For this reason, it’s usually a good idea to specify system fonts as a
fallback list. You can specify the value for font-family
as a comma-delimited list of
font names. The Flex application will try to use the first font on the
list, and if it cannot find that system font, it will use the next
font on the list.
font-family: Verdana, Arial, Helvetica;
Device fonts are not specific fonts, but rather names of font
categories. Flex recognizes three device fonts: _sans
, _serif
, and _typewriter
. These device fonts resolve to a
system font that is in a general font category. For example, _sans
usually resolves to Arial or
Helvetica, _serif
usually resolves
to Times New Roman, and _typewriter
usually resolves to Courier or Courier New. Using device fonts is a
way to virtually guarantee that the text will appear in a general
style (i.e., sans-serif, serif, or monotype). When you use a device
font name in CSS, you must enclose the value in quotation
marks:
font-family: "_sans";
Although there are use cases for system fonts and device fonts, the fonts most frequently used in Flex applications are embedded fonts. Embedded fonts compile the font outlines into the .swf, guaranteeing that all users will see the text in the same font. The potential downside of embedded fonts is that they increase the size of the .swf file. However, considering that Flex applications are rich Internet applications, the actual file size increase for an embedded font is usually insubstantial. The exception to that would be the use of extended characters and multibyte fonts, for use with languages such as Japanese and Chinese. Yet even in some of those cases, the file size increase can sometimes be mitigated by embedding only the outlines for the fonts required by the application.
There are other reasons to embed fonts besides wanting to guarantee consistent fonts for all users. Embedded fonts solve a few problems with system fonts. System fonts in Flex applications cannot be rotated, nor can you adjust the alpha of system fonts. If you attempt to rotate system fonts, the text disappears. If you attempt to adjust the alpha of a system font, you will not see an effect. However, if you embed the font, you can both rotate the text and adjust the alpha. Furthermore, system fonts are not anti-aliased. When you increase the size of system fonts the aliasing is more apparent, and it will look like the text has jagged edges. Embedded fonts are anti-aliased, meaning they look better at larger sizes. (Note that this is a double-edged sword because anti-aliased text is less legible at smaller font sizes. We’ll look at the solution to this in “Using FlashType” later in this chapter.)
There are a handful of ways to embed fonts. First we’ll look at
how to embed fonts when you have the font file (a .ttf file). You can embed these fonts using the Embed
metadata tag within ActionScript.
To embed the font this way use the source
attribute to specify the path to the .ttf file and the fontName
attribute to specify the name of the font as you will want to
reference it throughout your application. For the metadata tag to
work, you must place it just before a variable declaration of type
Class
. You will not need to use the
variable at all, but the compiler requires this.
Here’s an example that embeds a font called Century Gothic from
the .ttf file using the fontName
of gothicCentury
:
[Embed(source="GOTHIC.ttf", fontName="gothicCentury")] private var _centuryGothic:Class;
Once you’ve embedded the font, you can use the fontName
value to reference it just as you
would any other font, as shown in Example 8-6.
Example 8-6. Embedding a font using the Embed metadata tag
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> global { fontFamily: gothicCentury; } </mx:Style> <mx:Script> <![CDATA[ [Embed(source="GOTHIC.ttf", fontName="gothicCentury")] private var _centuryGothic:Class; ]]> </mx:Script> <mx:TextArea text="Example Text" /> </mx:Application>
When you embed a font, only one set of the font outlines is embedded. In Example 8-6, only the standard font outlines are embedded, not the bold or italic outlines. In Example 8-7, you can clearly see the effects of this when you try to add a button instance to the preceding example.
Example 8-7. Missing font outlines cause default fonts to appear
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
global {
fontFamily: gothicCentury;
}
</mx:Style>
<mx:Script>
<![CDATA[
[Embed(source="GOTHIC.ttf", fontName="gothicCentury")]
private var _centuryGothic:Class;
]]>
</mx:Script>
<mx:TextArea text="Example Text" />
<mx:Button label="Example" />
</mx:Application>
Because buttons default to using the bold version of a font, Example 8-7 will use the
Century Gothic font for the text area, but it will use the default
system font for the button label. To fix this, we must also embed the
bold font outlines for the same font using the same fontName
value. However, this time we need
to set the fontWeight
attribute
to bold
; see Example 8-8. (If you want to
embed the italicized font outlines, you should set fontStyle
to italic
.)
Example 8-8. Embedding standard and bold font outlines
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> global { fontFamily: gothicCentury; } </mx:Style> <mx:Script> <![CDATA[ [Embed(source="GOTHIC.ttf", fontName="gothicCentury")] private var _centuryGothic:Class; [Embed(source="GOTHICB.ttf", fontName="gothicCentury", fontWeight="bold")] private var _centuryGothicBold:Class; ]]> </mx:Script> <mx:TextArea text="Example Text" /> <mx:Button label="Example" /> </mx:Application>
You can also embed fonts from CSS using the @font-face
directive. This is particularly useful when you use external
stylesheets because then you can compile them to use as themes or as
runtime CSS. However, it’s also equally okay to use this technique for
local style definitions simply because you prefer the syntax to the
Embed
metadata tag. In the
following examples, we’ll use local style definitions for the sake of
simplicity and clarity.
The @font-face
directive
allows for all the same attributes/properties as the Embed
metadata tag when embedding fonts. The exceptions are that the
source attribute of the metadata tag is called src
in the @font-face
directive and fontName
from the metadata tag is called
fontFamily
in the directive.
Furthermore, the value of the src
attribute should be wrapped in url()
, as shown in the following
example:
@font-face { src: url("GOTHIC.ttf"); fontFamily: gothicCentury; }
Example 8-9 is
the earlier MXML example rewritten with @font-face
directives.
Example 8-9. Using the @font-face directive
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> @font-face { src: url("GOTHIC.ttf"); fontFamily: gothicCentury; } @font-face { src: url("GOTHICB.ttf"); fontFamily: gothicCentury; fontWeight: bold; } global { fontFamily: gothicCentury; } </mx:Style> <mx:TextArea text="Example Text" /> <mx:Button label="Example" /> </mx:Application>
Flex allows you to embed a font in a different manner as well.
Rather than embedding the font by way of the .ttf file, you can use the font name as
it’s recognized by the computer system. When you want to do this, you
can use the Embed
metadata tag.
Rather than using the source
attribute, you should use the
systemFont
and specify the name of the font as it’s known by the
system. Additionally, when you specify a system font name, you must
also specify the MIME type by using the mimeType
attribute. The value should be either application/x-font
or application/x-font-truetype
. Example 8-10 uses system font names to
embed fonts.
Example 8-10. Embedding fonts by system name
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> global { fontFamily: gothicCentury; } </mx:Style> <mx:Script> <![CDATA[ [Embed(systemFont="Century Gothic", fontName="gothicCentury", mimeType="application/x-font")] private var _centuryGothic:Class; [Embed(systemFont="Century Gothic", fontName="gothicCentury", fontWeight="bold", mimeType="application/x-font")] private var _centuryGothicBold:Class; ]]> </mx:Script> <mx:TextArea text="Example Text" /> <mx:Button label="Example" /> </mx:Application>
You can also embed fonts by name using CSS. To do so, you should wrap
the src
value using local()
rather than url()
. The following example illustrates how
this works:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> @font-face { src:local
("Century Gothic"); fontFamily: gothicCentury; } @font-face { src:local
("Century Gothic"); fontFamily: gothicCentury; fontWeight: bold; } global { fontFamily: gothicCentury; } </mx:Style> <mx:TextArea text="Example Text" /> <mx:Button label="Example" /> </mx:Application>
When you embed a font, by default all the outlines are
embedded, regardless of what characters are used in the application.
In some cases your application may not use all the font outlines, and
in those cases it's unnecessary and wasteful to embed all the font
outlines. For that reason, Flex lets you specify ranges of characters
to embed using the unicodeRange
attribute for @font-face
or
the Embed
metadata tag. The unicodeRange
attribute lets you
specify one or more Unicode values or ranges of Unicode values. The
Unicode values must be in the form U+
code
, such as
U+00A1
. You can specify ranges by
placing a hyphen between two values, as in U+00A1-U+00FF
. Specify more than one value or range by delimiting them
with commas, as in Example 8-11.
Example 8-11. Embedding font subset ranges
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> @font-face { src: url("GOTHIC.ttf"); fontFamily: gothicCentury; unicodeRange: U+0041-U+007F; } @font-face { src: url("GOTHICB.ttf"); fontFamily: gothicCentury; fontWeight: bold; unicodeRange: U+0041-U+007F; } global { fontFamily: gothicCentury; } </mx:Style> <mx:TextArea text="++ Example Text ++" /> <mx:Button label="Example" /> </mx:Application>
Example 8-11 embeds the range
of standard Latin alphabet characters, but not the +
character. That means the alphabetic
characters in the components show up, but the +
characters do not. Example 8-12 embeds the +
character as well.
Example 8-12. Embedding lists of font subsets
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> @font-face { src: url("GOTHIC.ttf"); fontFamily: gothicCentury; unicodeRange: U+0041-U+007F,U+002B
; } @font-face { src: url("GOTHICB.ttf"); fontFamily: gothicCentury; fontWeight: bold; unicodeRange: U+0041-U+007F,U+002B
; } global { fontFamily: gothicCentury; } </mx:Style> <mx:TextArea text="++ Example Text ++" /> <mx:Button label="Example" /> </mx:Application>
You can also use named ranges that you define in the compiler
configuration file you specify using the -load-config
attribute. If you want to add
named ranges to the compiler configuration file, you must add the
values in the following format:
<flex-config> <compiler> <fonts> <languages> <language-range> <lang>Alpha And Plus</lang> <range>U+0041-U+007F,U+002B</range> </language-range> </languages> </fonts> </compiler> </flex-config>
If you want to add more than one named range, you can simply
add more language-range
tags
nested within the languages
tag.
You can then specify the named range as the value for the
unicodeRange
attribute. The name must appear in quotes, as in Example 8-13.
Example 8-13. Embedding fonts by named ranges
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> @font-face { src: url("GOTHIC.ttf"); fontFamily: gothicCentury; unicodeRange: "Alpha And Plus"; } @font-face { src: url("GOTHICB.ttf"); fontFamily: gothicCentury; fontWeight: bold; unicodeRange: "Alpha And Plus"; } global { fontFamily: gothicCentury; } </mx:Style> <mx:TextArea text="++ Example Text ++" /> <mx:Button label="Example" /> </mx:Application>
To simplify things you can use predefined ranges. The predefined ranges are in the flash-unicode-table.xml document in the
frameworks subdirectory of the
SDK directory. If you want to use
these predefined ranges, you can copy and paste the language-range
tags from the
flash-unicode-table.xml document
to your configuration file.
In Flex 3 it is possible to leverage greater control over embedded fonts using something called advanced anti-aliasing. Advanced anti-aliasing allows you to control text appearance with additional styles:
fontSharpness
A value from −400 to 400 (the default value is 0) specifying how crisp the edges of the font appear. The higher the value is, the crisper the edges. Lowering the value for smaller fonts usually makes the fonts more legible.
fontThickness
A value from −200 to 200 (the default value is 0) specifying how thick the edges of the font should be.
Advanced anti-aliasing also allows you to use the fontAntiAliasType
and fontGridFitType
styles, which are beyond
the scope of this book. You can consult the Flex documentation for
more details on these styles.
Example 8-14 uses two sliders that allow you to adjust the sharpness and thickness of the font in order to see the effects.
Example 8-14. Adjusting FlashType properties
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Style> global { fontFamily: gothicCentury; fontSize: 50; } </mx:Style> <mx:Script> <![CDATA[ [Embed(systemFont="Century Gothic", fontName="gothicCentury", mimeType="application/x-font")] private var _centuryGothic:Class; [Embed(systemFont="Century Gothic", fontName="gothicCentury", fontWeight="bold", mimeType="application/x-font")] private var _centuryGothicBold:Class; private function sharpnessChangeHandler(event:Event):void { StyleManager.getStyleDeclaration("global").setStyle("fontSharpness", sharpnessSlider.value); } private function thicknessChangeHandler(event:Event):void { StyleManager.getStyleDeclaration("global").setStyle("fontThickness", thicknessSlider.value); } ]]> </mx:Script> <mx:Button label="Example" /> <mx:HSlider id="sharpnessSlider" value="0" minimum="−400" maximum="400" liveDragging="true" change="sharpnessChangeHandler(event)" /> <mx:HSlider id="thicknessSlider" value="0" minimum="−200" maximum="200" liveDragging="true" change="thicknessChangeHandler(event)" /> </mx:Application>
Advanced anti-aliasing is enabled for embedded fonts by default.
Although there is no difference in runtime performance between
advanced and nonadvanced anti-aliased fonts, there are compile-time
performance hits when using advanced anti-aliasing. If you don’t intend to use any of the styles enabled by
advanced anti-aliasing and you are embedding a lot of fonts and notice
compiler slowness, you can disable advanced anti-aliasing for the
fonts using the advancedAntiAliasing
attribute in the @font-face
directive or Embed
metadata
tag:
@font-face { src: url("GOTHIC.ttf"); fontFamily: gothicCentury; advancedAntiAliasing: false; }