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 <TextGraphic> or
+ * FXG 2.0 <RichText> 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 <TextGraphic> 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 <p> 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 <RichText> 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 <span> 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 <TextGraphic> 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;
+}