//////////////////////////////////////////////////////////////////////////////// // // 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 flashx.textLayout.conversion { import flash.utils.Dictionary; import flashx.textLayout.debug.assert; import flashx.textLayout.elements.ContainerFormattedElement; import flashx.textLayout.elements.DivElement; import flashx.textLayout.elements.FlowElement; import flashx.textLayout.elements.FlowGroupElement; import flashx.textLayout.elements.FlowValueHolder; import flashx.textLayout.elements.InlineGraphicElement; import flashx.textLayout.elements.LinkElement; import flashx.textLayout.elements.ParagraphFormattedElement; import flashx.textLayout.elements.SpanElement; import flashx.textLayout.elements.TCYElement; import flashx.textLayout.elements.TextFlow; import flashx.textLayout.formats.ITextLayoutFormat; import flashx.textLayout.formats.TextLayoutFormat; import flashx.textLayout.formats.WhiteSpaceCollapse; import flashx.textLayout.property.Property; import flashx.textLayout.tlf_internal; use namespace tlf_internal; [ExcludeClass] /** * @private * Export filter for TextLayout format. */ internal class TextLayoutExporter extends BaseTextLayoutExporter { private static var nameCounter:int = 0; static private var _formatDescription:Object= TextLayoutFormat.description; private var queuedExport:Object = null; public function TextLayoutExporter() { super(new Namespace("http://ns.adobe.com/textLayout/2008"), null, TextLayoutImporter.defaultConfiguration); } override protected function clear():void { nameCounter = 0; queuedExport = null; } /** Export text content of a TextFlow into TextLayout format. * @param source the text to export * @return XML the exported content */ protected override function exportToXML(textFlow:TextFlow) : XML { var result:XML = super.exportToXML(textFlow); var queuedXML:XMLList = exportQueuedObjects(); if (queuedXML) result.appendChild(queuedXML); return result; } private function exportQueuedObjects():XMLList { if (!queuedExport) return null; // pump out the queued objects var result:XMLList = new XMLList(); for (var idName:String in queuedExport) { var objectToExport:Object = queuedExport[idName]; var output:XMLList = new XMLList(); if (objectToExport is FlowValueHolder) { var characterFormatXML:XML = new XML(""); characterFormatXML.setNamespace(flowNS); output += characterFormatXML; output.@id = idName; exportStyles(output, objectToExport.coreStyles, formatDescription); exportStyles(output, objectToExport.userStyles); } result += output; } return result; } /** Get additional objects that are required for export * The subject may have dependent objects that will need to be exported, in addition * to the subject itself. * @return XML array of Objects to export */ private function queueForExport(object:Object, name:String):void { if (!queuedExport) queuedExport = new Object(); queuedExport[name] = object; } static private const brTabRegEx:RegExp = new RegExp("[" + "\u2028" + "\t" + "]"); // Doesn't /\u2028\t/ work? /** Gets the regex that specifies characters to be replaced with XML elements * Note: Each match is a single character */ protected override function get spanTextReplacementRegex():RegExp { return brTabRegEx; } /** Gets the xml element used to represent a character in the export format */ protected override function getSpanTextReplacementXML(ch:String):XML { var replacementXML:XML; if (ch == '\u2028') replacementXML =
; else if (ch == '\t') replacementXML = ; else { CONFIG::debug {assert(false, "Did not recognize character to be replaced with XML"); } return null; } replacementXML.setNamespace(flowNS); return replacementXML; } protected override function exportFlowElement(flowElement:FlowElement):XMLList { var rslt:XMLList = super.exportFlowElement(flowElement); var coreStyles:Object = flowElement.coreStyles; if (coreStyles) { // WhiteSpaceCollapse attribute should never be exported (except on TextFlow -- handled separately) delete coreStyles[TextLayoutFormat.whiteSpaceCollapseProperty.name]; exportStyles(rslt, coreStyles, formatDescription); } // export id and styleName if (flowElement.id != null) rslt.@["id"] = flowElement.id; if (flowElement.styleName != null) rslt.@["styleName"] = flowElement.styleName; // export any user defined styles var styles:Object = flowElement.userStyles; if (styles) exportStyles(rslt, styles); return rslt; } /** Base functionality for exporting an Image. Exports as a FlowElement, * and exports image properties. * @param exporter Root object for the export * @param image Element to export * @return XMLList XML for the element */ static public function exportImage(exporter:BaseTextLayoutExporter, image:InlineGraphicElement):XMLList { var output:XMLList = exportFlowElement(exporter, image); // output the img specific values if (image.height !== undefined) output.@height = image.height; if (image.width !== undefined) output.@width = image.width; // output.@rotation = image.rotation; don't support rotation yet if (image.source != null) output.@source = image.source; // FUTURE!!! output.@float = image.float; return output; } /** Base functionality for exporting a LinkElement. Exports as a FlowGroupElement, * and exports link properties. * @param exporter Root object for the export * @param link Element to export * @return XMLList XML for the element */ static public function exportLink(exporter:BaseTextLayoutExporter, link:LinkElement):XMLList { var output:XMLList = exportFlowGroupElement(exporter, link); if (link.href) output.@href= link.href; if (link.target) output.@target = link.target; return output; } /** Base functionality for exporting a DivElement. Exports as a FlowContainerFormattedElement * @param exporter Root object for the export * @param div Element to export * @return XMLList XML for the element */ static public function exportDiv(exporter:BaseTextLayoutExporter, div:DivElement):XMLList { return exportContainerFormattedElement(exporter, div); } /** Base functionality for exporting a TCYElement. Exports as a FlowGroupElement * @param exporter Root object for the export * @param tcy Element to export * @return XMLList XML for the element */ static public function exportTCY(exporter:BaseTextLayoutExporter, tcy:TCYElement):XMLList { return exportFlowGroupElement(exporter, tcy); } /** Queues the object for export later, generates an ID for it, and returns * the ID. * @param exporter Root object for the export * @param obj Element to export * @return String ID of the object */ static private function exportToName(exporter:BaseTextLayoutExporter, obj:Object):String { var newName:String = "ObjectID" + nameCounter.toString(); TextLayoutExporter(exporter).queueForExport(obj, newName); nameCounter++; return newName; } override protected function get formatDescription():Object { return _formatDescription; } } }