You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2014/07/22 15:35:46 UTC

[20/51] [partial] - Migrated the directory structure to a more Maven style structure. - Started migrating the Parser from Antlr2+3 and JFlex to Antlr4.

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexFXG2SWFTranscoder.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexFXG2SWFTranscoder.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexFXG2SWFTranscoder.java
new file mode 100644
index 0000000..aec3437
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexFXG2SWFTranscoder.java
@@ -0,0 +1,1306 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.flex;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.flex.compiler.common.Multiname;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.definitions.IClassDefinition;
+import org.apache.flex.compiler.definitions.IDefinition;
+import org.apache.flex.compiler.definitions.ITypeDefinition;
+import org.apache.flex.compiler.fxg.dom.IFXGNode;
+import org.apache.flex.compiler.fxg.swf.FXG2SWFTranscoder;
+import org.apache.flex.compiler.internal.fxg.dom.CDATANode;
+import org.apache.flex.compiler.internal.fxg.dom.GraphicContentNode;
+import org.apache.flex.compiler.internal.fxg.dom.GraphicNode;
+import org.apache.flex.compiler.internal.fxg.dom.GroupNode;
+import org.apache.flex.compiler.internal.fxg.dom.IMaskableNode;
+import org.apache.flex.compiler.internal.fxg.dom.IMaskingNode;
+import org.apache.flex.compiler.internal.fxg.dom.RichTextNode;
+import org.apache.flex.compiler.internal.fxg.dom.TextGraphicNode;
+import org.apache.flex.compiler.internal.fxg.dom.ITextNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.BRNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.DivNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.ImgNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.LinkNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.ParagraphNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.SpanNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.TCYNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.TabNode;
+import org.apache.flex.compiler.internal.fxg.dom.richtext.TextLayoutFormatNode;
+import org.apache.flex.compiler.internal.fxg.dom.types.BlendMode;
+import org.apache.flex.compiler.internal.fxg.dom.types.MaskType;
+import org.apache.flex.compiler.internal.projects.FlexProject;
+import org.apache.flex.compiler.internal.scopes.ASProjectScope;
+import org.apache.flex.compiler.problems.FXGDefinitionNotFoundProblem;
+import org.apache.flex.compiler.problems.FXGUndefinedPropertyProblem;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.projects.ICompilerProject;
+import org.apache.flex.swf.tags.DefineSpriteTag;
+import org.apache.flex.swf.tags.ICharacterTag;
+import org.apache.flex.swf.tags.ITag;
+import org.apache.flex.swf.tags.PlaceObject3Tag;
+import org.apache.flex.utils.StringUtils;
+
+/**
+ * This implementation generates ActionScript classes for features not supported
+ * in SWF tags. For example, ActionScript classes must be generated to draw
+ * FXG 1.0 TextGraphic nodes programmatically (using instances of the
+ * spark.components.RichText ActionScript class). To maintain a link between
+ * the DefineSpriteTag display list and a generated RichText wrapper class, a
+ * SWF SymbolClass is used and associated with the DefineSpriteTag.
+ * 
+ * Other features not supported in SWF that require ActionScript classes to be
+ * generated include alpha masks, luminosity masks, and pixel-bender based
+ * blend modes, namely: colordodge, colorburn, exclusion, softlight, hue,
+ * saturation, color, and luminosity.
+ */
+public class FlexFXG2SWFTranscoder extends FXG2SWFTranscoder
+{
+    private String packageName;
+
+    private final ICompilerProject project;
+
+    private final ITypeDefinition stringType;
+    private final ITypeDefinition objectType;
+    private final ITypeDefinition anyType;
+    
+    private final HashMap<String, Integer> nameCounter;
+    private Map<String, ITypeDefinition> dependencies;
+    
+    private static final String packageSpriteVisualElement = "spark.core.SpriteVisualElement";
+    private static final String packageShaderFilter = "spark.filters.ShaderFilter";
+    private static final String packageLuminosityMaskShader = "mx.graphics.shaderClasses.LuminosityMaskShader";
+    private static final String packageIFlexModuleFactory = "mx.core.IFlexModuleFactory";
+    private static final String packageFlashEvent = "flash.events.Event";    
+    private static final String packageBreakElement = "flashx.textLayout.elements.BreakElement";
+    private static final String packageDivElement = "flashx.textLayout.elements.DivElement";
+    private static final String packageLinkElement = "flashx.textLayout.elements.LinkElement";
+    private static final String packageImgElement = "flashx.textLayout.elements.InlineGraphicElement";
+    private static final String packageRichText = "spark.components.RichText";
+    private static final String packageParagraphElement = "flashx.textLayout.elements.ParagraphElement";
+    private static final String packageSpanElement = "flashx.textLayout.elements.SpanElement";
+    private static final String packageTabElement = "flashx.textLayout.elements.TabElement";
+    private static final String packageTCYElement = "flashx.textLayout.elements.TCYElement";
+    private static final String packageTextLayoutFormat = "flashx.textLayout.formats.TextLayoutFormat";
+    
+    /**
+     * Construct a Flex specific FXG to SWF tag transcoder.
+     */
+    public FlexFXG2SWFTranscoder(ICompilerProject project)
+    {
+        super();
+
+        this.project = project;
+
+        stringType = (ITypeDefinition)project.getBuiltinType(IASLanguageConstants.BuiltinType.STRING);
+        objectType = (ITypeDefinition)project.getBuiltinType(IASLanguageConstants.BuiltinType.OBJECT);
+        anyType = (ITypeDefinition)project.getBuiltinType(IASLanguageConstants.BuiltinType.ANY_TYPE);
+        
+        nameCounter = new HashMap<String, Integer>();
+        dependencies = new HashMap<String, ITypeDefinition>();
+    }
+
+    @Override
+    public FXGSymbolClass transcode(IFXGNode node, String packageName, String className, Map<ITag, ITag> extraTags, Collection<ICompilerProblem> problems)
+    {
+        this.packageName = packageName;
+        super.transcode(node, packageName, className, extraTags, problems);
+        
+        addDependency(packageSpriteVisualElement); //add dependency to the class we extend       
+        
+        // Create a new sprite class to map to this Graphic's DefineSpriteTag
+        StringBuilder buf = new StringBuilder(512);
+        buf.append("package ").append(packageName).append("\n");
+        buf.append("{\n\n");
+        buf.append("import ").append(packageSpriteVisualElement).append(";\n\n");
+        buf.append("public class ").append(className).append(" extends SpriteVisualElement\n");
+        buf.append("{\n");
+        buf.append("    public function ").append(className).append("()\n");
+        buf.append("    {\n");
+        buf.append("        super();\n");
+        if (node instanceof GraphicNode)
+        {
+            GraphicNode graphicNode = (GraphicNode)node;
+            if (!Double.isNaN(graphicNode.viewWidth))
+                buf.append("        viewWidth = ").append(graphicNode.viewWidth).append(";\n");
+
+            if (!Double.isNaN(graphicNode.viewHeight))
+                buf.append("        viewHeight = ").append(graphicNode.viewHeight).append(";\n");
+
+            if (graphicNode.getMaskType() == MaskType.ALPHA && graphicNode.mask != null)
+            {
+                int maskIndex = graphicNode.mask.getMaskIndex();
+                buf.append("        this.cacheAsBitmap = true;\n");
+                buf.append("        this.mask = this.getChildAt(").append(maskIndex).append(");\n");
+            }
+        }
+
+        buf.append("    }\n"); // End constructor
+		buf.append("}\n"); // End class
+        buf.append("}\n"); // End package
+
+        graphicClass.setGeneratedSource(buf.toString());
+        
+        return graphicClass;
+        
+    }
+    
+    /**
+     * Finds the definition {@link ITypeDefinition} for the specified qualified
+     * name and add this type to the list of classes/interfaces on which the FXG file 
+     * processed by this transcoder have dependency.
+     * 
+     * @param qname qualified name which to add the dependency to
+     */
+    private void addDependency(String qname)
+    {
+        getDefinition(qname);
+    }
+    
+    /**
+     * Returns the definition {@link ITypeDefinition} for the specified qualified
+     * name and add this type to the list of classes/interfaces on which the FXG file 
+     * processed by this transcoder have dependency.
+     * 
+     * @param qname qualified name for which to find the definition
+     * @return the definition for the specified qualified name or 
+     * <code>null</code> if definition cannot be resolved.
+     */
+    private ITypeDefinition getDefinition(String qname) 
+    {
+        ITypeDefinition definition = dependencies.get(qname);
+        
+        if(definition == null)
+        {
+            ASProjectScope scope = (ASProjectScope)project.getScope();
+            definition = (ITypeDefinition)scope.findDefinitionByName(Multiname.crackDottedQName(project, qname , true), true);
+            
+            if(definition == null) 
+            {
+                problems.add(new FXGDefinitionNotFoundProblem(qname));
+                return null;
+            } 
+                
+            dependencies.put(qname, definition);
+        }
+        
+        return definition;
+    }
+
+    
+    /**
+     * This override simply ensures that a FlexFXG2SWFTranscoder is created
+     * instead of an instance of the base class FXG2SWFTranscoder.
+     * 
+     * @return a new transcoder with an isolated context to process a Library
+     * Definition.
+     */
+    @Override
+    public FXG2SWFTranscoder newInstance()
+    {
+        FlexFXG2SWFTranscoder graphics = new FlexFXG2SWFTranscoder(project);
+        graphics.packageName = packageName;
+        graphics.graphicClass = graphicClass;
+        graphics.definitions = definitions;
+        graphics.extraTags = extraTags;
+        graphics.imageMap = imageMap;
+        graphics.depthMap = depthMap;
+        return graphics;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Advanced Graphics Code Generation
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     * This override handles advanced mask features not supported by SWF. This
+     * includes alpha and luminosity masks.
+     * 
+     * @param node - the node being masked (which has a reference to the mask
+     * node)
+     * @param parentSprite - the SWF DefineSpriteTag that will be the parent of
+     * this node when added to the display list
+     */
+    @Override
+    protected PlaceObject3Tag mask(IMaskableNode node, DefineSpriteTag parentSprite)
+    {
+        IMaskingNode mask = node.getMask();
+        PlaceObject3Tag po3 = super.mask(node, parentSprite); 
+
+        if (mask != null)
+        {
+            MaskType maskType = node.getMaskType(); 
+
+            if (maskType != MaskType.CLIP)
+            {
+                // Record the display list position that the mask was placed.
+                // The ActionScript display list is 0 based, but SWF the depth
+                // counter starts at 1, so we subtract 1.
+                int maskIndex = getSpriteDepth(parentSprite) - 1;
+                mask.setMaskIndex(maskIndex);
+            }
+
+            if (maskType == MaskType.LUMINOSITY)
+            {
+                // Create a new SymbolClass to map to this mask's
+                // DefineSpriteTag (see below)  
+                String className = createUniqueName(graphicClass.getClassName() + "_Mask");
+                FXGSymbolClass symbolClass = new FXGSymbolClass();
+                symbolClass.setPackageName(packageName);
+                symbolClass.setClassName(className);
+
+                // Then record this SymbolClass with the top-level graphic
+                // SymbolClass so that it will be associated with the FXG asset.
+                graphicClass.addAdditionalSymbolClass(symbolClass);
+
+                // Calculate luminosity mode
+                int mode = 0;
+
+                if (node.getLuminosityClip())
+                    mode += 2;
+
+                if (node.getLuminosityInvert())
+                    mode += 1;
+                
+                //Add required dependencies
+                addDependency(packageShaderFilter);
+                addDependency(packageLuminosityMaskShader);
+
+                StringBuilder buf = new StringBuilder(768);
+                buf.append("package ").append(packageName).append("\n");
+                buf.append("{\n\n");
+                buf.append("import flash.display.Sprite;\n");
+                buf.append("import ").append(packageShaderFilter).append(";\n");
+                buf.append("import ").append(packageLuminosityMaskShader).append(";\n\n");
+                buf.append("public class ").append(className).append(" extends Sprite\n");
+                buf.append("{\n");
+                buf.append("    public function ").append(className).append("()\n");
+                buf.append("    {\n");
+                buf.append("        super();\n");
+                buf.append("        this.cacheAsBitmap = true;\n");
+                buf.append("        var shader:LuminosityMaskShader = new LuminosityMaskShader();\n");
+                buf.append("        shader.mode = ").append(mode).append(";\n");
+                buf.append("        var filter:ShaderFilter = new ShaderFilter(shader);\n");
+                buf.append("        this.filters = [filter.clone()];\n");
+                buf.append("    }\n");
+                buf.append("}\n"); // End class
+                buf.append("}\n"); // End package
+
+                symbolClass.setGeneratedSource(buf.toString());
+                symbolClass.setSymbol(po3.getCharacter());
+            }
+        }
+
+        return po3;
+    }
+
+    @Override
+    /**
+     * This override handles graphic content nodes that make use of advanced
+     * graphics features not supported by SWF. A Group is translated into a 
+     * SWF DefineSpriteTag tag. Shapes are translated into SWF DefineShape tags.
+     * 
+     * @param node - the graphic content node
+     * @return the PlaceObjcet definition that would place the graphic on stage
+     */
+    protected PlaceObject3Tag graphicContentNode(GraphicContentNode node)
+    {
+        // Keep track of whether a node had a mask and filters as this
+        // scenario needs to be special cased to match the rendering order 
+        // of the ActionScript drawing API.
+        boolean hasMaskAndFilters = node.mask != null && node.filters != null;
+
+        PlaceObject3Tag po3 = super.graphicContentNode(node);
+
+        // We skip text nodes because they already generate a symbol class
+        // and will handle advanced graphics there
+        if (po3 != null && !(node instanceof ITextNode) && hasAdvancedGraphics(node))
+        {
+            SymbolClassType symbolClassType = SymbolClassType.SHAPE;
+            if (hasMaskAndFilters || (node instanceof GroupNode))
+                symbolClassType = SymbolClassType.SPRITE;
+
+            advancedGraphics(node, po3.getCharacter(), symbolClassType);
+        }
+
+        return po3;
+    }
+
+    @Override
+    /**
+     * This override handles Group nodes that make use of advanced
+     * graphics features not supported by SWF. Groups are translated into
+     * SWF DefineSpriteTags and can be linked to a SymbolClass that will use
+     * ActionScript to draw the advanced graphic features.
+     * 
+     * @param node - the Group node
+     * @return the PlaceObject3Tag definition that would place the Group on stage
+     */
+    protected PlaceObject3Tag group(GroupNode node)
+    {
+        PlaceObject3Tag po3 = super.group(node);
+
+        if (po3 != null && hasAdvancedGraphics(node))
+            advancedGraphics(node, po3.getCharacter(), SymbolClassType.SPRITE);
+
+        return po3;
+    }
+
+    /**
+     * Determines whether a node uses advanced graphics features which are not
+     * supported by the SWF format. If so, we will need to generate
+     * ActionScript code to instruct the player to draw the advanced features.
+     * 
+     * @param node - the graphics node that may make use of advanced graphics
+     * features
+     * @return true if advanced graphics features are in use
+     */
+    private boolean hasAdvancedGraphics(IMaskableNode node)
+    {
+        if (node.getMask() != null &&
+            (node.getMaskType() == MaskType.ALPHA ||
+             node.getMaskType() == MaskType.LUMINOSITY))
+        {
+            return true;
+        }
+        else if (node instanceof GraphicContentNode)
+        {
+            GraphicContentNode graphicNode = (GraphicContentNode)node;
+            if (graphicNode.blendMode.needsPixelBenderSupport())
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Some advanced graphics features are not supported by SWF. This helper
+     * method generates ActionScript instructions to handle advanced features
+     * such as alpha masks, luminosity masks, or pixel-bender based blend modes
+     * (e.g. colordodge, colorburn, exclusion, softlight, hue, saturation, 
+     * color, and luminosity).
+     * 
+     * @param node - an FXG node that uses advanced graphics features
+     * @param symbol - the SWF symbol for this node
+     * @param symbolClassType - determines the base type for the SymbolClass
+     */
+    private void advancedGraphics(GraphicContentNode node, ICharacterTag symbol,
+            SymbolClassType symbolClassType)
+    {
+        IMaskingNode maskNode = node.getMask();
+
+        // Create a new SymbolClass to map to this mask's
+        // DefineSpriteTag (see below)
+        String className = graphicClass.getClassName();
+        if (maskNode != null)
+            className += "_Maskee";
+
+        className = createUniqueName(className);
+
+        FXGSymbolClass symbolClass = new FXGSymbolClass();
+        symbolClass.setPackageName(packageName);
+        symbolClass.setClassName(className);
+
+        // Then record this SymbolClass with the top-level graphic
+        // SymbolClass so that it will be associated with the FXG asset.
+        graphicClass.addAdditionalSymbolClass(symbolClass);
+
+        StringBuilder buf = new StringBuilder(512);
+        buf.append("package ").append(packageName).append("\n");
+        buf.append("{\n\n");
+
+        // Determine Base Class
+        String baseClassName = null;
+        if (symbolClassType == SymbolClassType.SPRITE)
+        {
+            buf.append("import flash.display.Sprite;\n");
+            baseClassName = "Sprite";
+        }
+        else
+        {
+            buf.append("import flash.display.Shape;\n");
+            baseClassName = "Shape";
+        }
+
+        // Advanced BlendModes
+        String blendModeClass = null;
+        BlendMode blendmode = node.blendMode;
+        if(blendmode != null && blendmode.needsPixelBenderSupport()) {
+            blendModeClass = blendmode.getClassName();
+            
+            addDependency(blendModeClass); //add dependency to this class
+            buf.append("import ").append(blendModeClass).append(";\n\n");
+        }
+        
+        // Class Definition and Constructor
+        buf.append("public class ").append(className).append(" extends ").append(baseClassName).append("\n");
+        buf.append("{\n");
+        buf.append("    public function ").append(className).append("()\n");
+        buf.append("    {\n");
+        buf.append("        super();\n");
+        buf.append("        this.cacheAsBitmap = true;\n");
+
+        // Alpha and Luminosity Masks
+        if (maskNode != null)
+        {
+            int maskIndex = maskNode.getMaskIndex();
+            if (symbolClassType == SymbolClassType.SPRITE)
+                buf.append("        this.mask = this.getChildAt(").append(maskIndex).append(");\n");
+            else
+                buf.append("        this.mask = this.parent.getChildAt(").append(maskIndex).append(");\n");
+        }
+
+        // BlendMode Shader
+        if (blendModeClass != null)
+            buf.append("        this.blendShader = new ").append(Multiname.getBaseNameForQName(blendModeClass)).append("();\n");
+
+        buf.append("    }\n"); // End constructor
+        buf.append("}\n"); // End class
+        buf.append("}\n"); // End package
+
+        symbolClass.setGeneratedSource(buf.toString());
+        symbolClass.setSymbol(symbol);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  TextGraphic and RichText Code Generation
+    //
+    //--------------------------------------------------------------------------
+    
+    @Override
+    /**
+     * RichText is not supported by SWF. This override uses a Sprite-based
+     * ActionScript SymbolClass to create a spark.components.RichText instance
+     * to draw the text.
+     * 
+     * @param node - an FXG 2.0 RichText node
+     * @return the PlaceObject3Tag definition that would place the associated
+     * DefineSpriteTag on the stage
+     */
+    protected PlaceObject3Tag richtext(RichTextNode node)
+    {
+        return flexText(node);
+    }
+
+    @Override
+    /**
+     * TextGraphic is not supported by SWF. This override uses a Sprite-bsaed
+     * ActionScript SymbolClass to create a spark.components.RichText instance
+     * to draw the text.
+     * 
+     * @param node - an FXG 1.0 TextGraphic node
+     * @return the PlaceObject3Tag definition that would place the associated
+     * DefineSpriteTag on the stage
+     */
+    protected PlaceObject3Tag text(TextGraphicNode node)
+    {
+        return flexText(node);
+    }
+
+    /**
+     * Generates Flex specific ActionScript for FXG 1.0 &lt;TextGraphic&gt; or
+     * FXG 2.0 &lt;RichText&gt; nodes.
+     * 
+     * @param node - either a TextGraphicNode or RichTextNode.
+     * @return the PlaceObject3Tag definition that would place the associated
+     * DefineSpriteTag on the stage
+     */
+    private PlaceObject3Tag flexText(GraphicContentNode node)
+    {
+        if (node instanceof ITextNode)
+        {
+            ITextNode textNode = ((ITextNode)node);
+
+            // Create a new SymbolClass to map to this TextGraphic's
+            // DefineSpriteTag (see below)  
+            String className = createUniqueName(graphicClass.getClassName() + "_Text");
+
+            FXGSymbolClass spriteSymbolClass = new FXGSymbolClass();
+            spriteSymbolClass.setPackageName(packageName);
+            spriteSymbolClass.setClassName(className);
+
+            // Then record this SymbolClass with the top-level graphic
+            // SymbolClass so that it will be associated with the FXG asset.
+            graphicClass.addAdditionalSymbolClass(spriteSymbolClass);
+
+            // Create a DefineSpriteTag to hold this TextGraphic
+            DefineSpriteTag textSprite = createDefineSpriteTag(className);
+            PlaceObject3Tag po3 = PlaceObject3Tag(textSprite, node.createGraphicContext());
+            spriteStack.push(textSprite);
+            
+            //Add dependencies
+            addDependency(packageFlashEvent);
+            addDependency(packageTextLayoutFormat);
+            addDependency(packageIFlexModuleFactory);
+            addDependency(packageRichText);
+            addDependency(packageSpriteVisualElement);
+
+            StringBuilder buf = new StringBuilder(4096);
+            buf.append("package ").append(packageName).append("\n");
+            buf.append("{\n\n");
+            buf.append("import flashx.textLayout.elements.*;\n");
+            buf.append("import mx.core.mx_internal;\n");
+            buf.append("import ").append(packageFlashEvent).append(";\n");
+            buf.append("import ").append(packageTextLayoutFormat).append(";\n");
+            buf.append("import ").append(packageIFlexModuleFactory).append(";\n");
+            buf.append("import ").append(packageRichText).append(";\n");
+            buf.append("import ").append(packageSpriteVisualElement).append(";\n");
+            buf.append("use namespace mx_internal;\n\n");
+
+            // Advanced BlendModes
+            String blendModeClass = null;
+            BlendMode blendmode = node.blendMode;
+            if(blendmode != null && blendmode.needsPixelBenderSupport()) {
+                blendModeClass = blendmode.getClassName();
+                
+                addDependency(blendModeClass); //add dependency to this class
+                buf.append("import ").append(blendModeClass).append(";\n\n");
+            }
+
+            buf.append("public class ").append(className).append(" extends SpriteVisualElement\n");
+            buf.append("{\n");
+            buf.append("    public function ").append(className).append("()\n");
+            buf.append("    {\n");
+            buf.append("        super();\n");
+            buf.append("        this.nestedSpriteVisualElement = true;\n");
+
+            if (hasAdvancedGraphics(node))
+                buf.append("        this.cacheAsBitmap = true;\n");
+
+            // Alpha Masks
+            IMaskingNode maskNode = node.getMask();
+            if (maskNode != null &&
+                    (node.getMaskType() == MaskType.ALPHA ||
+                     node.getMaskType() == MaskType.LUMINOSITY))
+            {
+                int maskIndex = maskNode.getMaskIndex();
+                buf.append("        this.mask = this.parent.getChildAt(").append(maskIndex).append(");\n");
+            }
+
+            // BlendMode Shader
+            if (blendModeClass != null)
+                buf.append("        this.blendShader = new ").append(Multiname.getBaseNameForQName(blendModeClass)).append("();\n");
+
+            // Generate Text
+            buf.append("        createText();\n");
+            buf.append("    }\n");
+            buf.append("\n");
+            
+            buf.append("    private var _richTextComponent:RichText;\n\n");
+
+            buf.append("    private function createText():void\n");
+            buf.append("    {\n");
+
+            SourceContext textSource = generateRichText(textNode);
+            if (textSource.functionBuffer != null)
+                buf.append(textSource.functionBuffer.toString());
+
+            buf.append("    }\n");
+
+            if (textSource.classBuffer != null)
+                buf.append(textSource.classBuffer.toString());
+
+            buf.append(generateModuleFactoryOverride("_richTextComponent"));
+            
+            buf.append("}\n"); // End class
+            buf.append("}\n"); // End package
+
+            spriteSymbolClass.setGeneratedSource(buf.toString());
+            spriteSymbolClass.setSymbol(textSprite);
+
+            spriteStack.pop();
+            return po3;
+        }
+
+        return null;
+    }
+
+    /**
+     * Generates a unique name by appending a random number to the given base
+     * name.
+     * 
+     * @param baseName the base of the generated name 
+     * @return the unique name
+     */
+    private String createUniqueName(String baseName)
+    {
+        String suffix;
+        if (nameCounter.containsKey(baseName))
+        {
+            int counterValue = nameCounter.get(baseName) + 1;
+            nameCounter.put(baseName, counterValue);
+            suffix = String.valueOf(counterValue);
+        } else {
+            suffix = "0";
+            nameCounter.put(baseName, 0);
+        }
+        return baseName + '_' + suffix;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Methods for ActionScript Generation  
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     * Generates ActionScript code to initialize a new instance of
+     * RichText for a given FXG TextGraphic node, its attributes, and any
+     * child nodes.
+     * 
+     * @param node The TextGraphic node to process.
+     * 
+     * @return Returns the code generation buffers (for the function and
+     * potentially class scopes).
+     */
+    private SourceContext generateRichText(ITextNode textNode)
+    {
+        // Generate ActionScript equivalent of tag markup. We use 1024
+        // characters of generated code is sufficient for the initial size of
+        // the function scope buffer. We use 0 characters for the class scope
+        // buffer until we encounter the special case of:
+        //     <img source="@Embed('...')">
+        // which involves generating class member variables to embed images.
+        SourceContext srcContext = new SourceContext(1024, 0);
+        StringBuilder buf = srcContext.functionBuffer;
+        
+        Variables varContext = new Variables();
+        IClassDefinition definition = (IClassDefinition)getDefinition(packageRichText);
+        
+        if(definition != null)
+        {
+            varContext.setVar(definition, NodeType.RICHTEXT);
+            String elementVar = varContext.elementVar;
+
+            generateTextVariable(textNode, srcContext, varContext);
+
+            buf.append("        _richTextComponent = ").append(elementVar).append(";\r\n");
+            buf.append("        addChild(").append(elementVar).append(");\r\n");
+
+            buf.append("        var addHandler:Function = function(event:Event):void\r\n");
+            buf.append("        {\r\n");
+            buf.append("            removeEventListener(Event.ADDED_TO_STAGE, addHandler);\r\n\r\n");
+
+            buf.append("            // If we don't have a module factory by now then use the root\r\n");
+            buf.append("            if (moduleFactory == null && root is IFlexModuleFactory)\r\n");
+            buf.append("                moduleFactory = IFlexModuleFactory(root);\r\n");
+
+            buf.append("        };\r\n");
+            buf.append("        addEventListener(Event.ADDED_TO_STAGE, addHandler);\r\n");
+        }
+
+        return srcContext;
+    }
+    
+    /**
+     * Create a module factory override so we do not try to use a RichText's styles until we 
+     * have a module factory. The module factory will tell us which style manager to use.
+     * 
+     * @param elementVar
+     * @return
+     */
+    private String generateModuleFactoryOverride(String elementVar)
+    {
+        StringBuilder buf = new StringBuilder(1024);
+
+        buf.append("\r\n    /**\r\n");
+        buf.append("     *  @private\r\n");
+        buf.append("     *  Create a module factory override so we do not try to use a RichText's\r\n");
+        buf.append("     *  styles until we have a module factory. The module factory will tell us\r\n");
+        buf.append("     *  which style manager to use.\r\n");
+        buf.append("     */\r\n");
+        buf.append("    override public function set moduleFactory(factory:IFlexModuleFactory):void\r\n");
+        buf.append("    {\r\n");
+        
+        //TODO: This line causes a stack overflow, even though the super class has the same setter. 
+        //Bug filed against falcon for this: <will file a bug for this as soon as I come up with a basic repro case>
+        //Uncomment this when the bug is fixed.
+        //buf.append("        super.moduleFactory = factory;\r\n");
+        
+        buf.append("        ").append(elementVar).append(".regenerateStyleCache(true);\r\n");
+        buf.append("        ").append(elementVar).append(".styleChanged(null);\r\n");        
+        buf.append("        ").append(elementVar).append(".stylesInitialized();\r\n");
+        buf.append("        ").append(elementVar).append(".validateProperties();\r\n");
+        buf.append("        ").append(elementVar).append(".validateSize();\r\n");
+        buf.append("        ").append(elementVar).append(".setLayoutBoundsSize(NaN, NaN);\r\n");
+        buf.append("        ").append(elementVar).append(".validateDisplayList();\r\n");
+        buf.append("        invalidateSize();\r\n");
+        buf.append("    }\r\n");
+        
+        return buf.toString();
+    }
+
+    /**
+     * Generates ActionScript to initialize a variable for a given text node,
+     * populates any specified attributes as properties or styles, and
+     * recursively processes any text child nodes.
+     * @param textNode - the current text node
+     * @param srcContext - the current code generation buffers
+     * @param varContext - the current generated ActionScript variable context 
+     */
+    private void generateTextVariable(ITextNode textNode,
+            SourceContext srcContext, Variables varContext)
+    {
+        StringBuilder buf = srcContext.functionBuffer;
+        Map<String, String> attributes = textNode.getTextAttributes();
+        List<ITextNode> children = textNode.getTextChildren();
+
+        String currentVar = varContext.elementVar;
+        String contentVar = varContext.contentVar;
+        String parentClass = varContext.elementClass;
+        String parentChildrenVar = varContext.elementChildrenVar;
+        IClassDefinition type = varContext.type;
+
+        if (!varContext.varDeclared)
+        {
+            // var someElement:SomeElement = new SomeElement();
+            buf.append("        var ").append(currentVar).append(":").append(parentClass).append(" = new ").append(parentClass).append("();\r\n");
+
+            // var someContent:Array = [];
+            if (contentVar != null)
+                buf.append("        var ").append(contentVar).append(":Array = [];\r\n");
+        }
+        else
+        {
+            // someElement = new SomeElement();
+            buf.append("        ").append(currentVar).append(" = new ").append(parentClass).append("();\r\n");
+
+            // someContent = [];
+            if (contentVar != null)
+                buf.append("        ").append(contentVar).append(" = [];\r\n");
+        }
+
+        // Attributes
+        generateAttributes(textNode, type, attributes, srcContext, currentVar);
+
+        // Properties
+        // Note: We process RichTextNode properties after content has been assigned.
+        if (!(textNode instanceof RichTextNode))
+            generateProperties(srcContext, textNode, currentVar, varContext);
+
+        // Child Nodes
+        if (children != null && children.size() > 0)
+        {
+            Iterator<ITextNode> iter = children.iterator();
+            while (iter.hasNext())
+            {
+                String elementVar = null;
+                ITextNode child = iter.next();
+                IClassDefinition definition = null;
+                
+                // FXG 2.0
+                if (child instanceof RichTextNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageRichText);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition, NodeType.RICHTEXT);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else if (child instanceof ParagraphNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageParagraphElement);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition, NodeType.PARAGRAPH);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else if (child instanceof SpanNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageSpanElement);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition, NodeType.SPAN);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else if (child instanceof DivNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageDivElement);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition, NodeType.DIV);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else if (child instanceof CDATANode)
+                {
+                    // someContent.push("some text");
+                    String text = formatString(((CDATANode)child).content);
+                    buf.append("        ").append(contentVar).append(".push(").append(text).append(");\r\n");
+                }
+                else if (child instanceof BRNode)
+                {
+                    addDependency(packageBreakElement);
+                    buf.append("        ").append(contentVar).append(".push(new BreakElement());\r\n");
+                }
+                else if (child instanceof ImgNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageImgElement);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition,NodeType.IMG);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else if (child instanceof LinkNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageLinkElement);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition,NodeType.LINK);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else if (child instanceof TabNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageTabElement);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition,NodeType.TAB);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else if (child instanceof TCYNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageTCYElement);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition,NodeType.TCY);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                // FXG 1.0
+                else if (child instanceof TextGraphicNode)
+                {
+                    definition = (IClassDefinition)getDefinition(packageRichText);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition,NodeType.RICHTEXT);
+                        elementVar = varContext.elementVar;
+                        generateTextVariable(child, srcContext, varContext);
+                        buf.append("        ").append(contentVar).append(".push(").append(elementVar).append(");\r\n");
+                    }
+                }
+                else
+                {
+                    //Should not happen. Ignore this.
+                }
+            }
+        }
+
+        // e.g. someElement.mxmlChildren = someContent;
+        if (parentChildrenVar != null && contentVar != null)
+            buf.append("        ").append(currentVar).append(".").append(parentChildrenVar).append(" = ").append(contentVar).append(";\r\n");
+
+        // RichText is a special case whose properties must be set after content
+        // is assigned and the textFlow has been populated.
+        if (textNode instanceof RichTextNode)
+            generateProperties(srcContext, textNode, currentVar, varContext);
+    }
+
+    /**
+     * Generates ActionScript code for child property nodes that represent
+     * complex property values. It also generates the property assignment 
+     * statement.
+     * 
+     * @param srcContext - the ActionScript source code generation buffers.
+     * @param parentNode - the parent ITextNode to process for properties  
+     * @param parentVar - the parent variable that declares the properties
+     * @param varContext - the current context for generating variables in
+     * ActionScript code 
+     */
+    private void generateProperties(SourceContext srcContext, ITextNode parentNode,
+            String parentVar, Variables varContext)
+    {
+        Map<String, ITextNode> properties = parentNode.getTextProperties(); 
+        if (properties != null)
+        {
+            StringBuilder buf = srcContext.functionBuffer;
+
+            for (Map.Entry<String, ITextNode> entry : properties.entrySet())
+            {
+                String propertyName = entry.getKey();
+                ITextNode node = entry.getValue();
+
+                if (node instanceof TextLayoutFormatNode)
+                {
+                    IClassDefinition definition = (IClassDefinition)getDefinition(packageTextLayoutFormat);
+                    if(definition != null)
+                    {
+                        varContext.setVar(definition, NodeType.TEXT_LAYOUT_FORMAT);
+                        generateTextVariable(node, srcContext, varContext);
+
+                        // RichText does not support setting text layout formatting
+                        // at the top level so we must update its textFlow instead.
+                        if (parentNode instanceof RichTextNode)
+                        {
+                            buf.append("        ").append(parentVar).append(".textFlow.").append(
+                                    propertyName).append(" = ").append(varContext.elementVar).append(";\r\n");
+                        }
+                        else
+                        {
+                            buf.append("        ").append(parentVar).append(".").append(
+                                    propertyName).append(" = ").append(varContext.elementVar).append(";\r\n");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Converts the attributes specified on an FXG node into ActionScript
+     * property initializers.
+     * 
+     * @param type The ActionScript type for this node.
+     * @param attributes The Map of attributes specified on this node.
+     * @param srcContext The source code generation buffers.
+     * @param variableName The ActionScript variable name representing the
+     * instance of this node.
+     */
+    private void generateAttributes(ITextNode node, IClassDefinition type, Map<String, String> attributes,
+            SourceContext srcContext, String variableName)
+    {
+        if (attributes != null)
+        {
+            StringBuilder buf = srcContext.functionBuffer;
+
+            // Handle <img source="@Embed('xyz.jpg')" /> as a special case
+            if (node instanceof ImgNode)
+            {
+                String imgSource = attributes.get("source");
+                imgSource = parseSource(imgSource);
+                if (imgSource != null)
+                {
+                    // Resolve relative file path
+                    File f = new File(imgSource);
+                    if (!f.isAbsolute() && resourceResolver != null)
+                    {
+                        String resolvedPath = resourceResolver.resolve(imgSource);
+                        if (resolvedPath != null)
+                            imgSource = resolvedPath;
+                    }
+                    imgSource = imgSource.replace('\\', '/');
+
+                    // Generate [Embed] for the image.
+                    if (srcContext.classBuffer == null)
+                        srcContext.classBuffer = new StringBuilder(128);
+                    StringBuilder classBuf = srcContext.classBuffer;
+                    String imgVar = createUniqueName("img");
+                    classBuf.append("\n");
+                    classBuf.append("    [Embed(source=\"").append(imgSource).append("\")]\n");
+                    classBuf.append("    private static var ").append(imgVar).append(":Class;\n");
+
+                    // Generate source attribute assignment
+                    buf.append("        ").append(variableName).append(".source = ").append(imgVar).append(";\n");
+
+                    attributes.remove("source");
+                }
+            }
+            
+            for (Map.Entry<String, String> entry : attributes.entrySet())
+            {
+                String attribName = entry.getKey();
+                String attribValue = entry.getValue();
+                String thisAttrib = null;
+                
+                IDefinition propertyDefinition = ((FlexProject)project).resolveProperty(type, attribName);
+                if (propertyDefinition != null) //is it a property?
+                {
+                    ITypeDefinition propertyType = propertyDefinition.resolveType(project);
+                    if (propertyType.isInstanceOf(stringType, project)
+                        || propertyType == objectType
+                        || propertyType == anyType)
+                    {
+                        thisAttrib = attribName + " = \"" + attribValue + "\"";
+                    }
+                    else
+                    {
+                         thisAttrib = attribName + " = " + attribValue;
+                    }
+                }
+                else if (((FlexProject)project).resolveStyle(type, attribName) != null) //is it a style?
+                {
+                    thisAttrib = "setStyle(\"" + attribName + "\", \"" + attribValue + "\")";
+                }
+                else
+                {
+                    problems.add(new FXGUndefinedPropertyProblem(attribName));
+                    continue;
+                }
+
+                if (thisAttrib != null)
+                    buf.append("        " + variableName + '.' + thisAttrib + ";\r\n");
+            }
+        }
+    }
+
+    /**
+     * Quotes a String and escapes any special characters so that it can be
+     * used as a literal ActionScript value.
+     * 
+     * @param content the raw String
+     * @return a Quoted String suitable for use as an ActionScript value. 
+     */
+    private String formatString(String content)
+    {
+        if (content != null)
+            return StringUtils.formatString(content);
+
+        return content;
+    }
+    
+    @Override
+    public ITypeDefinition[] getDependencies() 
+    {
+        return dependencies.values().toArray(new ITypeDefinition[0]);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    // Helper Classes for ActionScript Source Code Generation
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     * An enumeration that specifies the base type of a SymbolClass.
+     */
+    private static enum SymbolClassType
+    {
+        SPRITE,
+        SHAPE
+    }
+    
+    /**
+     * Text node type enumeration.
+     */
+    private static enum NodeType
+    {
+        DIV,
+        FORMAT,
+        IMG,
+        LINK,
+        PARAGRAPH,
+        RICHTEXT,
+        SPAN,
+        TAB,
+        TCY,
+        TEXT_LAYOUT_FORMAT
+    }
+
+    /**
+     * Provides a context to the current ActionScript generation buffers.
+     * Multiple buffers allow code to be generated in different parts of an
+     * ActionScript file, such as generating a class scope member while 
+     * generating a function scope.
+     */
+    private static class SourceContext
+    {
+        /**
+         * Constructor.
+         * @param functionSize - Initial function buffer size.
+         * @param classSize - Initial class buffer size.
+         */
+        private SourceContext(int functionSize, int classSize)
+        {
+            if (functionSize > 0)
+                functionBuffer = new StringBuilder(functionSize);
+
+            if (classSize > 0)
+                classBuffer = new StringBuilder(classSize);
+        }
+
+        private StringBuilder functionBuffer;
+        private StringBuilder classBuffer;
+    }
+    
+    /**
+     * Provides a context of variables in use for ActionScript source
+     * generation of a text node and its children.
+     */
+    private static class Variables
+    {
+        private Variable divVar;
+        private Variable formatVar;
+        private Variable imgVar;
+        private Variable linkVar;
+        private Variable paragraphVar;
+        private Variable richTextVar;
+        private Variable spanVar;
+        private Variable tabVar;
+        private Variable tcyVar;
+        private Variable textLayoutFormatVar;
+
+        private Variables()
+        {
+        }
+
+        private void setVar(IClassDefinition type, NodeType nodeType)
+        {
+            this.type = type;
+            Variable var = getVar(nodeType);
+            if (var != null)
+            {
+                var.count++;
+                if (!var.reusableVar)
+                {
+                    varDeclared = false;
+                    elementVar = var.elementVar + var.count;
+                    contentVar = var.contentVar + var.count;
+                }
+                else
+                {
+                    varDeclared = var.count > 1;
+                    elementVar = var.elementVar;
+                    contentVar = var.contentVar;
+                }
+                elementClass = var.elementClass;
+                elementChildrenVar = var.elementChildrenVar;
+            }
+        }
+
+        private Variable getVar(NodeType nodeType)
+        {
+            switch (nodeType)
+            {
+                case DIV:
+                {
+                    if (divVar == null)
+                        divVar = new Variable("DivElement", "divElement", "divContent", "mxmlChildren", false);
+                    return divVar; 
+                }
+                case FORMAT:
+                {
+                    if (formatVar == null)
+                        formatVar = new Variable("TextLayoutFormat", "formatElement", null, null, false);
+                    return formatVar;
+                }
+                case IMG:
+                {
+                    if (imgVar == null)
+                        imgVar = new Variable("InlineGraphicElement", "imgElement", null, null, true);
+                    return imgVar;
+                }
+                case LINK:
+                {
+                    if (linkVar == null)
+                        linkVar = new Variable("LinkElement", "linkElement", "linkContent", "mxmlChildren", true);
+                    return linkVar;
+                }
+                case PARAGRAPH:
+                {
+                    if (paragraphVar == null)
+                        paragraphVar = new Variable("ParagraphElement", "paragraphElement", "paragraphContent", "mxmlChildren", true);
+                    return paragraphVar;
+                }
+                case RICHTEXT:
+                {
+                    if (richTextVar == null)
+                        richTextVar = new Variable("RichText", "textElement", "textContent", "content", true);
+                    return richTextVar;
+                }
+                case SPAN:
+                {
+                    if (spanVar == null)
+                        spanVar = new Variable("SpanElement", "spanElement", "spanContent", "mxmlChildren", true);
+                    return spanVar;
+                }
+                case TAB:
+                {
+                    if (tabVar == null)
+                        tabVar = new Variable("TabElement", "tabElement", null, null, true);
+                    return tabVar;
+                }
+                case TCY:
+                {
+                    if (tcyVar == null)
+                        tcyVar = new Variable("TCYElement", "tcyElement", "tcyContent", "mxmlChildren", true);
+                    return tcyVar;
+                }
+                case TEXT_LAYOUT_FORMAT:
+                {
+                    if (textLayoutFormatVar == null)
+                        textLayoutFormatVar = new Variable("TextLayoutFormat", "tlfElement", null, null, true);
+                    return textLayoutFormatVar;
+                }
+            }
+
+            return null;
+        }
+
+        private IClassDefinition type;
+        private boolean varDeclared;
+        private String elementClass;
+        private String elementVar;
+        private String contentVar;
+        private String elementChildrenVar;
+    }
+
+    /**
+     * The context for an individual variable.
+     */
+    private static class Variable
+    {
+        private Variable(String elementClass, String elementVar, String contentVar, String elementChildrenVar, boolean reusableVar)
+        {
+            this.elementClass = elementClass;
+            this.elementVar = elementVar;
+            this.contentVar = contentVar;
+            this.elementChildrenVar = elementChildrenVar;
+            this.reusableVar = reusableVar;
+        }
+
+        private int count;
+        private boolean reusableVar;
+        private String elementClass;
+        private String elementVar;
+        private String contentVar;
+        private String elementChildrenVar;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexGraphicNode.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexGraphicNode.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexGraphicNode.java
new file mode 100644
index 0000000..8540b86
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexGraphicNode.java
@@ -0,0 +1,31 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.flex;
+
+import org.apache.flex.compiler.internal.fxg.dom.GraphicNode;
+
+/**
+ * A Flex specific override for GraphicNode used to record whether the
+ * FXG document includes any &lt;TextGraphic&gt; child nodes.
+ */
+public class FlexGraphicNode extends GraphicNode
+{
+    public boolean hasText;
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexParagraphNode.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexParagraphNode.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexParagraphNode.java
new file mode 100644
index 0000000..c64dbb7
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexParagraphNode.java
@@ -0,0 +1,58 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.flex;
+
+import java.util.Collection;
+
+import org.apache.flex.compiler.internal.fxg.dom.text.AbstractTextNode;
+import org.apache.flex.compiler.internal.fxg.dom.text.ParagraphNode;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+
+/**
+ * A Flex specific override for ParagraphNode used catch attributes that need to
+ * be renamed on a &lt;p&gt; tag.
+ */
+public class FlexParagraphNode extends ParagraphNode
+{
+    /**
+     * Flex specific override to keep track of attributes that need to be
+     * renamed.
+     * 
+     * @param name the attribute name
+     * @param value the attribute value
+     * @see ParagraphNode#setAttribute(String, String, Collection)
+     * @see AbstractTextNode#setAttribute(String, String, Collection)
+     */
+    @Override
+    public void setAttribute(String name, String value, Collection<ICompilerProblem> problems)
+    {
+        super.setAttribute(name, value, problems);
+
+        // Translate FXG attributes to equivalent Flex properties
+        String newName = FlexTextGraphicNode.translateAttribute(name);
+        if (!name.equals(newName))
+        {
+            if (textAttributes != null)
+                textAttributes.remove(name);
+
+            rememberAttribute(newName, value);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexRichTextNode.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexRichTextNode.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexRichTextNode.java
new file mode 100644
index 0000000..9b82fd4
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexRichTextNode.java
@@ -0,0 +1,96 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.flex;
+
+import org.apache.flex.compiler.fxg.dom.IFXGNode;
+import org.apache.flex.compiler.internal.fxg.dom.GraphicContext;
+import org.apache.flex.compiler.internal.fxg.dom.RichTextNode;
+
+/**
+ * A Flex specific override for RichTextNode used to capture the 
+ * attributes specified on a &lt;RichText&gt; node in FXG 2.0.
+ */
+public class FlexRichTextNode extends RichTextNode
+{
+    /**
+     * Constructor.
+     */
+    public FlexRichTextNode()
+    {
+        super();
+    }
+
+    /**
+     * If the document root is a FlexGraphicNode, it records that the document
+     * makes use of TextGraphic and thus will need to generate symbol classes to
+     * programmatically draw the text (as there is no equivalent to TextGraphic
+     * in SWF).
+     */
+    @Override
+    public void setDocumentNode(IFXGNode root)
+    {
+        super.setDocumentNode(root);
+
+        if (root instanceof FlexGraphicNode)
+        {
+            ((FlexGraphicNode)root).hasText = true;
+        }
+    }
+
+    /**
+     * Since RichText is converted to a sprite based ActionScript class
+     * and rendered using Flex's RichText API, we do not report
+     * attributes on the graphic context that are going to be set as properties
+     * in ActionScript (as otherwise you would end up with duplicate
+     * transformations).
+     * <p>
+     * The ignored graphic context attributes include:
+     * <pre>
+     * x="..."
+     * y="..."
+     * scaleX="..."
+     * scaleY="..."
+     * rotation="..."
+     * blendMode="..."
+     * alpha="..."
+     * </pre>
+     * </p>
+     */
+    @Override
+    public GraphicContext createGraphicContext()
+    {
+        GraphicContext graphicContext = new GraphicContext();
+
+        if (colorTransform != null)
+        {
+            graphicContext.colorTransform = colorTransform;
+        }
+
+        if (filters != null)
+            graphicContext.addFilters(filters);
+
+        if (maskTypeSet)
+            graphicContext.maskType = maskType;
+
+        return graphicContext;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexSpanNode.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexSpanNode.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexSpanNode.java
new file mode 100644
index 0000000..45e7a02
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexSpanNode.java
@@ -0,0 +1,58 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.flex;
+
+import java.util.Collection;
+
+import org.apache.flex.compiler.internal.fxg.dom.text.AbstractTextNode;
+import org.apache.flex.compiler.internal.fxg.dom.text.SpanNode;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+
+/**
+ * A Flex specific override for SpanNode used to capture the 
+ * attributes specified on a &lt;span&gt; node in FXG.
+ */
+public class FlexSpanNode extends SpanNode
+{
+    /**
+     * Flex specific override to keep track of the attributes set on this
+     * span node.
+     * 
+     * @param name the attribute name
+     * @param value the attribute value
+     * @see SpanNode#setAttribute(String, String, Collection)
+     * @see AbstractTextNode#setAttribute(String, String, Collection)
+     */
+    @Override
+    public void setAttribute(String name, String value, Collection<ICompilerProblem> problems)
+    {
+        super.setAttribute(name, value, problems);
+
+        // Translate FXG attributes to equivalent Flex properties
+        String newName = FlexTextGraphicNode.translateAttribute(name);
+        if (!name.equals(newName))
+        {
+            if (textAttributes != null)
+                textAttributes.remove(name);
+
+            rememberAttribute(newName, value);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexTextGraphicNode.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexTextGraphicNode.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexTextGraphicNode.java
new file mode 100644
index 0000000..49e2925
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/flex/FlexTextGraphicNode.java
@@ -0,0 +1,161 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.flex;
+
+import static org.apache.flex.compiler.fxg.FXGConstants.FXG_FONTFAMILY_ATTRIBUTE;
+import static org.apache.flex.compiler.fxg.FXGConstants.FXG_MARGINBOTTOM_ATTRIBUTE;
+import static org.apache.flex.compiler.fxg.FXGConstants.FXG_MARGINLEFT_ATTRIBUTE;
+import static org.apache.flex.compiler.fxg.FXGConstants.FXG_MARGINRIGHT_ATTRIBUTE;
+import static org.apache.flex.compiler.fxg.FXGConstants.FXG_MARGINTOP_ATTRIBUTE;
+import static org.apache.flex.compiler.fxg.FXGConstants.FXG_TRACKING_ATTRIBUTE;
+
+import java.util.Collection;
+
+import org.apache.flex.compiler.fxg.dom.IFXGNode;
+import org.apache.flex.compiler.internal.fxg.dom.GraphicContext;
+import org.apache.flex.compiler.internal.fxg.dom.TextGraphicNode;
+import org.apache.flex.compiler.internal.fxg.dom.text.AbstractTextNode;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+
+/**
+ * A Flex specific override for TextGraphicNode used to capture the 
+ * attributes specified on a &lt;TextGraphic&gt; node in FXG 1.0.
+ */
+public class FlexTextGraphicNode extends TextGraphicNode
+{
+    private static final String FXG_TRACKING_RIGHT_PROPERTY = "trackingRight"; 
+    private static final String FXG_PARAGRAPH_START_INDENT_PROPERTY = "paragraphStartIndent";
+    private static final String FXG_PARAGRAPH_SPACE_BEFORE_PROPERTY = "paragraphSpaceBefore";
+    private static final String FXG_PARAGRAPH_END_INDENT_PROPERTY = "paragraphEndIndent";
+    private static final String FXG_PARAGRAPH_SPACE_AFT_PROPERTY = "paragraphSpaceAft";
+
+    private static final String DEFAULT_FXG_FONT_FAMILY = "Times New Roman";
+
+    /**
+     * Constructor.
+     */
+    public FlexTextGraphicNode()
+    {
+        super();
+        // Set TextGraphic defaults that should always be set. 
+        setAttribute(FXG_FONTFAMILY_ATTRIBUTE, DEFAULT_FXG_FONT_FAMILY, null);
+    }
+
+    /**
+     * Flex specific override to keep track of the attributes set on this
+     * TextGraphic node.
+     * 
+     * @param name the attribute name
+     * @param value the attribute value
+     * @see TextGraphicNode#setAttribute(String, String, Collection)
+     * @see AbstractTextNode#setAttribute(String, String, Collection)
+     */
+    @Override
+    public void setAttribute(String name, String value, Collection<ICompilerProblem> problems)
+    {
+        super.setAttribute(name, value, problems);
+
+        // Translate FXG attributes to equivalent Flex properties
+        String newName = FlexTextGraphicNode.translateAttribute(name);
+        if (!name.equals(newName))
+        {
+            if (textAttributes != null)
+                textAttributes.remove(name);
+
+            rememberAttribute(newName, value);
+        }
+    }
+
+    /**
+     * If the document root is a FlexGraphicNode, it records that the document
+     * makes use of TextGraphic and thus will need to generate symbol classes to
+     * programmatically draw the text (as there is no equivalent to TextGraphic
+     * in SWF).
+     */
+    @Override
+    public void setDocumentNode(IFXGNode root)
+    {
+        super.setDocumentNode(root);
+
+        if (root instanceof FlexGraphicNode)
+        {
+            ((FlexGraphicNode)root).hasText = true;
+        }
+    }
+
+    /**
+     * Since TextGraphic is converted to a sprite based ActionScript class
+     * and rendered using Flex's RichText API, we do not report
+     * attributes on the graphic context that are going to be set as properties
+     * in ActionScript (as otherwise you would end up with duplicate
+     * transformations).
+     * <p>
+     * The ignored graphic context attributes include:
+     * <pre>
+     * x="..."
+     * y="..."
+     * scaleX="..."
+     * scaleY="..."
+     * rotation="..."
+     * blendMode="..."
+     * alpha="..."
+     * </pre>
+     * </p>
+     */
+    @Override
+    public GraphicContext createGraphicContext()
+    {
+        GraphicContext graphicContext = new GraphicContext();
+
+        if (colorTransform != null)
+        {
+            graphicContext.colorTransform = colorTransform;
+        }
+
+        if (filters != null)
+            graphicContext.addFilters(filters);
+
+        if (maskTypeSet)
+            graphicContext.maskType = maskType;
+
+        return graphicContext;
+    }
+
+    /**
+     * Converts an FXG attribute name to a Flex property name.
+     *  
+     * @param name
+     */
+    static String translateAttribute(String name)
+    {
+        if (FXG_TRACKING_ATTRIBUTE.equals(name))
+            name = FXG_TRACKING_RIGHT_PROPERTY;
+        else if (FXG_MARGINLEFT_ATTRIBUTE.equals(name))
+            name = FXG_PARAGRAPH_START_INDENT_PROPERTY;
+        else if (FXG_MARGINTOP_ATTRIBUTE.equals(name))
+            name = FXG_PARAGRAPH_SPACE_BEFORE_PROPERTY;
+        else if (FXG_MARGINRIGHT_ATTRIBUTE.equals(name))
+            name = FXG_PARAGRAPH_END_INDENT_PROPERTY;
+        else if (FXG_MARGINBOTTOM_ATTRIBUTE.equals(name))
+            name = FXG_PARAGRAPH_SPACE_AFT_PROPERTY;
+
+        return name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLog.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLog.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLog.java
new file mode 100644
index 0000000..65168ad
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLog.java
@@ -0,0 +1,58 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.logging;
+
+/**
+ * Utility API to get access to the logger for the current thread from anywhere
+ * in the library.
+ */
+public class FXGLog
+{
+    private static ThreadLocal<IFXGLogger> currentLogger = new ThreadLocal<IFXGLogger>();
+
+    private FXGLog()
+    {
+    }
+
+    /**
+     * @return The logger for the current thread. 
+     */
+    public static IFXGLogger getLogger()
+    {
+        IFXGLogger logger = currentLogger.get();
+
+        if (logger == null)
+        {
+            logger = FXGLoggerFactory.createDefaultLogger();
+            setLogger(logger);
+        }
+
+        return logger;
+    }
+
+    /**
+     * Sets the logger for the current thread. 
+     */
+    public static void setLogger(IFXGLogger value)
+    {
+        currentLogger.set(value);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLoggerFactory.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLoggerFactory.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLoggerFactory.java
new file mode 100644
index 0000000..7cbd327
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/FXGLoggerFactory.java
@@ -0,0 +1,39 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.logging;
+
+import org.apache.flex.compiler.internal.fxg.logging.SystemLogger;
+
+/**
+ * A simple factory to create an instance of an IFXGLogger implementation.
+ */
+public class FXGLoggerFactory
+{
+    /**
+     * Creates a new instance of the default implementation of IFXGLogger.
+     * 
+     * @return an IFXGLogger instance
+     * @see IFXGLogger 
+     */
+    public static IFXGLogger createDefaultLogger()
+    {
+        return new SystemLogger();
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/IFXGLogger.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/IFXGLogger.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/IFXGLogger.java
new file mode 100644
index 0000000..0015611
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/logging/IFXGLogger.java
@@ -0,0 +1,56 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.logging;
+
+/**
+ * A simple interface to report information while processing an FXG docuemnt.
+ */
+public interface IFXGLogger
+{
+    static final int ALL = 0;
+    static final int DEBUG = 10000;
+    static final int INFO = 20000;
+    static final int WARN = 30000;
+    static final int ERROR = 40000;
+    static final int NONE = Integer.MAX_VALUE;
+
+    int getLevel();
+    void setLevel(int level);
+
+    void debug(Object message);
+    void debug(Object message, Throwable t);
+    void debug(Object message, Throwable t, String location, int line, int column);
+
+    void error(Object message);
+    void error(Object message, Throwable t);
+    void error(Object message, Throwable t, String location, int line, int column);
+
+    void info(Object message);
+    void info(Object message, Throwable t);
+    void info(Object message, Throwable t, String location, int line, int column);
+
+    void log(int level, Object message);
+    void log(int level, Object message, Throwable t);
+    void log(int level, Object message, Throwable t, String location, int line, int column);
+
+    void warn(Object message);
+    void warn(Object message, Throwable t);
+    void warn(Object message, Throwable t, String location, int line, int column);
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/package.html
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/package.html b/compiler/src/main/java/org/apache/flex/compiler/fxg/package.html
new file mode 100644
index 0000000..58212a9
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/package.html
@@ -0,0 +1,31 @@
+<!--
+
+  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.
+
+-->
+
+<html>
+<body>
+
+This package and its subpackages contains classes and interfaces
+for compiling FXG.
+
+<p>
+This is mostly legacy code from the old <code>mxmlc</code> compiler.
+</p>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/FXGResourceResolverFactory.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/FXGResourceResolverFactory.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/FXGResourceResolverFactory.java
new file mode 100644
index 0000000..7cf1b1e
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/FXGResourceResolverFactory.java
@@ -0,0 +1,40 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.resources;
+
+import org.apache.flex.compiler.internal.fxg.resources.FXGFileResolver;
+
+/**
+ * A simple factory used to create an instance of a ResourceResolver
+ * implementation.
+ */
+public class FXGResourceResolverFactory
+{
+    /**
+     * Creates a new instance of the default implementation of IFXGParser.
+     * 
+     * @return an IFXGParser instance
+     * @see org.apache.flex.compiler.fxg.IFXGParser 
+     */
+    public static IFXGResourceResolver createDefaultResourceResolver()
+    {
+        return new FXGFileResolver();
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/IFXGResourceResolver.java
----------------------------------------------------------------------
diff --git a/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/IFXGResourceResolver.java b/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/IFXGResourceResolver.java
new file mode 100644
index 0000000..a5e29ce
--- /dev/null
+++ b/compiler/src/main/java/org/apache/flex/compiler/fxg/resources/IFXGResourceResolver.java
@@ -0,0 +1,41 @@
+/*
+ *
+ *  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 org.apache.flex.compiler.fxg.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * Implementations of ResourceResolver are used to locate and load resources,
+ * such as embedded images, while processing an FXG DOM.
+ */
+public interface IFXGResourceResolver
+{
+	String getRootPath();
+	
+	void setRootPath(String dir);
+
+	String resolve(String path);
+	
+	InputStream openStream(String path) throws IOException;
+
+	InputStream openStream(URL url) throws IOException;
+}