1////////////////////////////////////////////////////////////////////////////////
2//
3//  ADOBE SYSTEMS INCORPORATED
4//  Copyright 2008 Adobe Systems Incorporated
5//  All Rights Reserved.
6//
7//  NOTICE: Adobe permits you to use, modify, and distribute this file
8//  in accordance with the terms of the license agreement accompanying it.
9//
10////////////////////////////////////////////////////////////////////////////////
11
12package spark.utils
13{
14
15import flash.text.TextFormat;
16import flash.text.engine.ElementFormat;
17import flash.text.engine.FontDescription;
18import flash.text.engine.FontLookup;
19import flash.text.engine.TextBlock;
20import flash.text.engine.TextElement;
21import flash.text.engine.TextLine;
22
23import flashx.textLayout.compose.ISWFContext;
24
25import mx.core.IEmbeddedFontRegistry;
26import mx.core.IFlexModuleFactory;
27import mx.core.IUIComponent;
28import mx.core.Singleton;
29import mx.managers.ISystemManager;
30import mx.styles.IStyleClient;
31
32[ExcludeClass]
33
34/**
35 *  @private
36 */
37public class FTETextUtil
38{
39    include "../core/Version.as";
40
41    //--------------------------------------------------------------------------
42    //
43    //  Methods - Font Baseline
44    //
45    //--------------------------------------------------------------------------
46
47    //--------------------------------------------------------------------------
48    //
49    //  Class properties
50    //
51    //--------------------------------------------------------------------------
52
53    /**
54     *  @private
55     *  Used in getEmbeddedFontContext().
56     */
57    private static var staticTextFormat:TextFormat;
58
59    //----------------------------------
60    //  embeddedFontRegistry
61    //----------------------------------
62
63    private static var noEmbeddedFonts:Boolean;
64
65    /**
66     *  @private
67     *  Storage for the _embeddedFontRegistry property.
68     *  Note: This gets initialized on first access,
69     *  not when this class is initialized, in order to ensure
70     *  that the Singleton registry has already been initialized.
71     */
72    private static var _embeddedFontRegistry:IEmbeddedFontRegistry;
73
74    /**
75     *  @private
76     *  A reference to the embedded font registry.
77     *  Single registry in the system.
78     *  Used to look up the moduleFactory of a font.
79     */
80    private static function get embeddedFontRegistry():IEmbeddedFontRegistry
81    {
82        if (!_embeddedFontRegistry && !noEmbeddedFonts)
83        {
84            try
85            {
86                _embeddedFontRegistry = IEmbeddedFontRegistry(
87                    Singleton.getInstance("mx.core::IEmbeddedFontRegistry"));
88            }
89            catch (e:Error)
90            {
91                noEmbeddedFonts = true;
92            }
93        }
94
95        return _embeddedFontRegistry;
96    }
97
98    //--------------------------------------------------------------------------
99    //
100    //  Class methods
101    //
102    //--------------------------------------------------------------------------
103
104    /**
105     *  Method to measure baseline position
106     *
107     *  @param client The IStyleClient to use to calculate the baseline.
108     *  @param height Height of client.  Used only for degenerate cases.
109     *  @param moduleFactory The default moduleFactory to use for the font.
110     */
111    public static function calculateFontBaseline(client:IStyleClient, height:Number, moduleFactory:IFlexModuleFactory):Number
112    {
113        var fontDescription:FontDescription = new FontDescription();
114        var embeddedFontContext:IFlexModuleFactory;
115
116        var s:String;
117
118        s = client.getStyle("cffHinting");
119        if (s != null)
120            fontDescription.cffHinting = s;
121
122        s = client.getStyle("fontFamily");
123        if (s != null)
124            fontDescription.fontName = s;
125
126        s = client.getStyle("fontLookup");
127        if (s != null)
128        {
129            // FTE understands only "device" and "embeddedCFF"
130            // for fontLookup. But Flex allows this style to be
131            // set to "auto", in which case we automatically
132            // determine it based on whether the CSS styles
133            // specify an embedded font.
134            if (s == "auto")
135            {
136                embeddedFontContext = getEmbeddedFontContext(client, moduleFactory);
137                s = (embeddedFontContext) ?
138                    FontLookup.EMBEDDED_CFF :
139                    FontLookup.DEVICE;
140            }
141            fontDescription.fontLookup = s;
142        }
143
144        s = client.getStyle("fontStyle");
145        if (s != null)
146            fontDescription.fontPosture = s;
147
148        s = client.getStyle("fontWeight");
149        if (s != null)
150            fontDescription.fontWeight = s;
151
152        var elementFormat:ElementFormat = new ElementFormat();
153        elementFormat.fontDescription = fontDescription;
154        elementFormat.fontSize = client.getStyle("fontSize");
155
156        var textElement:TextElement = new TextElement();
157        textElement.elementFormat = elementFormat;
158        textElement.text = "Wj";
159
160        var textBlock:TextBlock = new TextBlock();
161        textBlock.content = textElement;
162
163        var textLine:TextLine;
164        if (embeddedFontContext)
165        {
166            var swfContext:ISWFContext = ISWFContext(embeddedFontContext);
167            textLine = swfContext.callInContext(
168						textBlock.createTextLine, textBlock,
169						[ null, 1000]);
170        }
171        else
172            textLine = textBlock.createTextLine(null, 1000);
173
174        if (height < 2 + textLine.ascent + 2)
175            return int(height + (textLine.ascent - height) / 2);
176
177        return 2 + textLine.ascent;
178    }
179
180	/**
181	 *  @private
182	 *  Uses the component's CSS styles to determine the module factory
183	 *  that should creates its TextLines.
184	 */
185    private static function getEmbeddedFontContext(client:IStyleClient, moduleFactory:IFlexModuleFactory):IFlexModuleFactory
186	{
187		var fontContext:IFlexModuleFactory;
188
189		var fontLookup:String = client.getStyle("fontLookup");
190		if (fontLookup != FontLookup.DEVICE)
191        {
192			var font:String = client.getStyle("fontFamily");
193			var bold:Boolean = client.getStyle("fontWeight") == "bold";
194			var italic:Boolean = client.getStyle("fontStyle") == "italic";
195
196            var localLookup:ISystemManager;
197            if (moduleFactory != null && moduleFactory is ISystemManager)
198                localLookup = ISystemManager(moduleFactory);
199            else if (client is IUIComponent)
200            {
201                var uic:IUIComponent = IUIComponent(client);
202                if (uic.parent is IUIComponent)
203                    localLookup = IUIComponent(uic.parent).systemManager;
204            }
205
206            fontContext = embeddedFontRegistry.getAssociatedModuleFactory(
207            	font, bold, italic, client, moduleFactory, localLookup, true);
208        }
209
210        if (!fontContext && fontLookup == FontLookup.EMBEDDED_CFF)
211        {
212            // if we couldn't find the font and somebody insists it is
213            // embedded, try the default fontContext
214            fontContext = moduleFactory;
215        }
216
217        return fontContext;
218	}
219
220}
221
222}
223