| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.core |
| { |
| |
| import flash.system.Capabilities; |
| import flash.text.FontStyle; |
| import flash.text.TextField; |
| import flash.text.TextFormat; |
| import flash.text.engine.FontDescription; |
| import flash.utils.Dictionary; |
| import flash.utils.getQualifiedClassName; |
| |
| import mx.managers.ISystemManager; |
| import mx.resources.IResourceManager; |
| import mx.resources.ResourceManager; |
| |
| use namespace mx_internal; |
| |
| [ExcludeClass] |
| |
| /** |
| * @private |
| * A singleton to contain a list of all the embeded fonts in use |
| * and the associated SWF/moduleFactory where the fonts are defined. |
| */ |
| public class EmbeddedFontRegistry implements IEmbeddedFontRegistry |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private static var fonts:Object = {}; |
| |
| /** |
| * @private |
| */ |
| private static var cachedFontsForObjects:Dictionary = new Dictionary(true); |
| |
| /** |
| * @private |
| */ |
| private static var instance:IEmbeddedFontRegistry; |
| |
| /** |
| * @private |
| * Used for accessing localized Error messages. |
| */ |
| private var _resourceManager:IResourceManager; |
| |
| /** |
| * @private |
| */ |
| private static var staticTextFormat:TextFormat = new TextFormat(); |
| |
| /** |
| * @private |
| */ |
| private static var flaggedObjects:Dictionary = new Dictionary(true); |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| public static function getInstance():IEmbeddedFontRegistry |
| { |
| if (!instance) |
| instance = new EmbeddedFontRegistry(); |
| |
| return instance; |
| } |
| |
| /** |
| * @private |
| * Creates a key for the embedded font. |
| * |
| * @param font FlexFont object, may not be null. |
| * |
| * @return String key |
| */ |
| private static function createFontKey(font:EmbeddedFont):String |
| { |
| return font.fontName + font.fontStyle; |
| } |
| |
| /** |
| * Creates an EmbeddedFont from a font key. |
| * |
| * @param key A string that represents a key |
| * created by createFontKey(); may not be null. |
| * |
| * @return An EmbeddedFont with the attributes from the key. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private static function createEmbeddedFont(key:String):EmbeddedFont |
| { |
| var fontName:String; |
| var fontBold:Boolean; |
| var fontItalic:Boolean; |
| |
| var index:int = endsWith(key,FontStyle.REGULAR); |
| if (index > 0) |
| { |
| fontName = key.substring(0, index); |
| return new EmbeddedFont(fontName, false, false); |
| } |
| |
| index = endsWith(key, FontStyle.BOLD); |
| if (index > 0) |
| { |
| fontName = key.substring(0, index); |
| return new EmbeddedFont(fontName, true, false); |
| } |
| |
| index = endsWith(key, FontStyle.BOLD_ITALIC); |
| if (index > 0) |
| { |
| fontName = key.substring(0, index); |
| return new EmbeddedFont(fontName, true, true); |
| } |
| |
| index = endsWith(key, FontStyle.ITALIC); |
| if (index > 0) |
| { |
| fontName = key.substring(0, index); |
| return new EmbeddedFont(fontName, false, true); |
| } |
| |
| return new EmbeddedFont("", false, false); |
| } |
| |
| /** |
| * Tests if a string ends with another string. |
| * |
| * @returns index into string if it ends with the matching string, otherwise returns -1. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| private static function endsWith(s:String, match:String):int |
| { |
| var index:int = s.lastIndexOf(match); |
| |
| if (index > 0 && (index + match.length == s.length)) |
| { |
| return index; |
| } |
| |
| return -1; |
| } |
| |
| /** |
| * @private |
| * Registers fonts from the info["fonts"] startup information. |
| * |
| * @param fonts Object obtained from the info["fonts"] call |
| * on a moduleFactory object. |
| * |
| * @param moduleFactory The module factory of the caller. |
| */ |
| public static function registerFonts(fonts:Object, |
| moduleFactory:IFlexModuleFactory):void |
| { |
| var fontRegistry:IEmbeddedFontRegistry; |
| try |
| { |
| fontRegistry = IEmbeddedFontRegistry( |
| Singleton.getInstance("mx.core::IEmbeddedFontRegistry")); |
| } |
| catch (e:Error) |
| { |
| Singleton.registerClass("mx.core::IEmbeddedFontRegistry", EmbeddedFontRegistry); |
| fontRegistry = IEmbeddedFontRegistry( |
| Singleton.getInstance("mx.core::IEmbeddedFontRegistry")); |
| } |
| |
| // Loop thru all the font objects and put them in the registry |
| for (var f:Object in fonts) |
| { |
| var fontObj:Object = fonts[f]; |
| |
| // For each value of "regular", "bold", "italic", and "boldItalic" |
| // register the font name. |
| for (var fieldIter:String in fontObj) |
| { |
| if (fontObj[fieldIter] == false) |
| continue; // no font to register |
| |
| var bold:Boolean; |
| var italic:Boolean; |
| if (fieldIter == "regular") |
| { |
| bold = false; |
| italic = false; |
| } |
| else if (fieldIter == "boldItalic") |
| { |
| bold = true; |
| italic = true; |
| } |
| else if (fieldIter == "bold") |
| { |
| bold = true; |
| italic = false; |
| } |
| else if (fieldIter == "italic") |
| { |
| bold = false; |
| italic = true; |
| } |
| |
| fontRegistry.registerFont( |
| new EmbeddedFont(String(f), bold, italic), moduleFactory); |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * |
| * The EmbeddedFontRegistry can be created in frame1 when an RSL loads a font. Defer creating |
| * a resource manager until it is needed. |
| * |
| */ |
| private function get resourceManager():IResourceManager |
| { |
| if (!_resourceManager) |
| _resourceManager = ResourceManager.getInstance(); |
| |
| return _resourceManager; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Convert a font styles into a String as using by flash.text.FontStyle. |
| * |
| * @param bold true if the font is bold, false otherwise. |
| * |
| * @param italic true if the font is italic, false otherwise. |
| * |
| * @return A String that matches one of the values in flash.text.FontStyle. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getFontStyle(bold:Boolean, italic:Boolean):String |
| { |
| var style:String = FontStyle.REGULAR; |
| |
| if (bold && italic) |
| style = FontStyle.BOLD_ITALIC; |
| else if (bold) |
| style = FontStyle.BOLD; |
| else if (italic) |
| style = FontStyle.ITALIC; |
| |
| return style; |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function registerFont(font:EmbeddedFont, |
| moduleFactory:IFlexModuleFactory):void |
| { |
| var fontKey:String = createFontKey(font); |
| var fontDictionary:Dictionary = fonts[fontKey]; |
| if (!fontDictionary) |
| { |
| fontDictionary = new Dictionary(true); // use weak ref for keys |
| fonts[fontKey] = fontDictionary; |
| } |
| fontDictionary[moduleFactory] = 1; |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function deregisterFont(font:EmbeddedFont, |
| moduleFactory:IFlexModuleFactory):void |
| { |
| var fontKey:String = createFontKey(font); |
| var fontDictionary:Dictionary = fonts[fontKey]; |
| if (fontDictionary != null) |
| { |
| delete fontDictionary[moduleFactory]; |
| |
| var count:int = 0; |
| for (var obj:Object in fontDictionary) |
| { |
| count++; |
| } |
| |
| if (count == 0) |
| delete fonts[fontKey]; |
| } |
| } |
| |
| /** |
| * Returns true if the embedded font with the given characteristics is |
| * in the <code>moduleFactory</code>, otherwise returns false. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 10 |
| * @playerversion AIR 1.5 |
| * @productversion Flex 4 |
| */ |
| public function isFontRegistered(font:EmbeddedFont, |
| moduleFactory:IFlexModuleFactory):Boolean |
| { |
| var fontKey:String = createFontKey(font); |
| var fontDictionary:Dictionary = fonts[fontKey]; |
| |
| return fontDictionary && fontDictionary[moduleFactory] == 1; |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getFonts():Array |
| { |
| var fontArray:Array = []; |
| |
| for (var key:String in fonts) |
| { |
| fontArray.push(createEmbeddedFont(key)); |
| } |
| |
| return fontArray; |
| } |
| |
| /** |
| * @inheritDoc |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getAssociatedModuleFactory( |
| fontName:String, bold:Boolean, italic:Boolean, |
| object:Object, |
| defaultModuleFactory:IFlexModuleFactory, |
| systemManager:ISystemManager, |
| embeddedCff:*=undefined): |
| IFlexModuleFactory |
| { |
| |
| var font:EmbeddedFont; |
| font = cachedFontsForObjects[object]; |
| if (!font) |
| { |
| font = new EmbeddedFont(fontName, bold, italic); |
| cachedFontsForObjects[object] = font; |
| } |
| else |
| { |
| // replace if not the same |
| if (font.fontName != fontName || |
| font.bold != bold || |
| font.italic != italic) |
| { |
| font = new EmbeddedFont(fontName, bold, italic); |
| cachedFontsForObjects[object] = font; |
| } |
| |
| } |
| var result:IFlexModuleFactory; |
| var fontDictionary:Dictionary = fonts[createFontKey(font)]; |
| if (fontDictionary) |
| { |
| // First lookup in the dictionary. If not found, then |
| // take the first moduleFactory in the dictionary. |
| // A module can register a font that is not unique and still |
| // use that font as long as its components specify the moduleFactory. |
| // A module can use fonts in other modules but |
| // to get consistent behavior the font should be unique. |
| var found:int = fontDictionary[defaultModuleFactory]; |
| |
| if (found) |
| result = defaultModuleFactory; |
| else |
| { |
| for (var iter:Object in fontDictionary) |
| { |
| result = iter as IFlexModuleFactory; |
| break; |
| } |
| } |
| } |
| |
| if (!result && systemManager) |
| { |
| // If we found the font, then it is embedded. Some fonts are not |
| // listed in info() and are therefore not resolvable with our |
| // registry, so we call isFontFaceEmbedded() which gets the list |
| // of embedded fonts from the player. |
| staticTextFormat.font = fontName; |
| staticTextFormat.bold = bold; |
| staticTextFormat.italic = italic; |
| |
| if (systemManager.isFontFaceEmbedded(staticTextFormat)) |
| result = systemManager; |
| } |
| |
| // We must ensure that the requested font is in fact valid for our |
| // given usage and context. |
| if (result && embeddedCff != undefined && Capabilities.isDebugger) |
| { |
| var compatible:Boolean = embeddedCff ? |
| result.callInContext(FontDescription.isFontCompatible, null, |
| [fontName, bold ? "bold" : "normal", italic ? "italic" : "normal"]) : |
| result.callInContext(TextField.isFontCompatible, null, |
| [fontName, getFontStyle(bold, italic)]); |
| |
| if (!compatible) |
| { |
| // We want to avoid reporting redundant warnings so we keep tabs |
| // on which instances we've already flagged as incompatible. |
| if (!flaggedObjects[object]) |
| { |
| var objName:String = getQualifiedClassName(object); |
| objName += "name" in object && object.name != null ? " ("+object.name+") " : ""; |
| trace(resourceManager.getString( "core", "fontIncompatible", |
| [fontName, objName, embeddedCff])); |
| flaggedObjects[object] = true; |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| } |
| |
| } |