| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 com.flexcapacitor.utils { |
| import com.flexcapacitor.model.IDocument; |
| import com.flexcapacitor.utils.supportClasses.ComponentDescription; |
| import com.flexcapacitor.views.supportClasses.Styles; |
| |
| import flash.display.BitmapData; |
| import flash.display.DisplayObject; |
| import flash.display.JPEGEncoderOptions; |
| import flash.display.PNGEncoderOptions; |
| import flash.geom.Rectangle; |
| import flash.utils.ByteArray; |
| import flash.utils.Dictionary; |
| import flash.utils.getTimer; |
| |
| import mx.core.IUIComponent; |
| import mx.core.IVisualElement; |
| import mx.core.IVisualElementContainer; |
| import mx.graphics.codec.JPEGEncoder; |
| import mx.graphics.codec.PNGEncoder; |
| import mx.styles.IStyleClient; |
| import mx.utils.Base64Encoder; |
| |
| import spark.components.BorderContainer; |
| import spark.components.HGroup; |
| import spark.components.supportClasses.GroupBase; |
| import spark.layouts.BasicLayout; |
| import spark.layouts.HorizontalLayout; |
| import spark.layouts.TileLayout; |
| import spark.layouts.VerticalLayout; |
| import spark.utils.BitmapUtil; |
| |
| /** |
| * Exports a document to HTML |
| * */ |
| public class HTMLDocumentExporter extends DocumentExporter { |
| |
| public function HTMLDocumentExporter() { |
| |
| } |
| |
| /** |
| * Sets explicit size regardless if size is explicit |
| * */ |
| public var setExplicitSize:Boolean = true; |
| |
| /** |
| * Sets styles inline |
| * */ |
| public var useInlineStyles:Boolean; |
| |
| /** |
| * Name of token in the template that is replaced by the |
| * */ |
| public var contentToken:String = "<!--template_content-->"; |
| |
| /** |
| * CSS to add to |
| * */ |
| public var css:String; |
| |
| /** |
| * Adds border box CSS |
| * */ |
| public var borderBoxCSS:String; |
| |
| /** |
| * Show outline |
| * */ |
| public var showBordersCSS:String; |
| |
| /** |
| * Zoom CSS |
| * */ |
| public var zoomCSS:String; |
| |
| /** |
| * Page zoom level |
| * */ |
| public var scaleLevel:Number; |
| |
| /** |
| * CSS for SVG button |
| * */ |
| public var buttonCSS:String; |
| |
| public var buttonCSS2:String; |
| |
| public var stylesheets:String; |
| |
| public var template:String; |
| |
| /** |
| * Creates a snapshot of the application and sets it as the background image |
| * */ |
| public var showScreenshotBackground:Boolean = false; |
| |
| /** |
| * Alpha of the background image |
| * */ |
| public var backgroundImageAlpha:Number = .5; |
| |
| /** |
| * Used to create PNG images |
| * */ |
| public var pngEncoder:PNGEncoder; |
| |
| /** |
| * Used to create JPEG images |
| * */ |
| public var jpegEncoder:JPEGEncoder; |
| |
| /** |
| * Extension of the document when exporting to a file. |
| * */ |
| public var extension:String; |
| |
| /** |
| * Indicates when the user has typed in the text area |
| * */ |
| [Bindable] |
| public var isCodeModifiedByUser:Boolean; |
| |
| /** |
| * Show borders around HTML elements |
| * */ |
| [Bindable] |
| public var showBorders:Boolean; |
| |
| /** |
| * Use SVG button class |
| * */ |
| [Bindable] |
| public var useSVGButtonClass:Boolean = true; |
| |
| /** |
| * Show full HTML page source |
| * */ |
| [Bindable] |
| public var showFullHTMLPageSource:Boolean = false; |
| |
| /** |
| * Last source code |
| * */ |
| [Bindable] |
| public var sourceCode:String; |
| |
| public var includePreviewCode:Boolean; |
| |
| public var horizontalPositions:Array = ["x","left","right","horizontalCenter"]; |
| public var horizontalCenterPosition:String = "horizontalCenter"; |
| public var verticalPositions:Array = ["y","top","bottom","verticalCenter"]; |
| public var verticalCenterPosition:String = "verticalCenter"; |
| public var sizesPositions:Array = ["width","height"]; |
| |
| public var addZoom:Boolean; |
| public var output:String = ""; |
| public var cssOutput:String = ""; |
| public var wrapInPreview:Boolean; |
| |
| /** |
| * |
| * */ |
| public var useWrapperDivs:Boolean; |
| public var showOnlyHTML:Boolean; |
| public var showOnlyCSS:Boolean; |
| |
| /** |
| * @inheritDoc |
| * */ |
| public function export(iDocument:IDocument, reference:Boolean = false, target:Object = null):String { |
| var XML1:XML; |
| var application:Object = iDocument ? iDocument.instance : null; |
| var targetDescription:ComponentDescription; |
| var componentTree:ComponentDescription; |
| var zoomOutput:String; |
| var xml:XML; |
| |
| componentTree = iDocument.componentDescription; |
| cssOutput = ""; |
| |
| // find target in display list and get it's code |
| targetDescription = DisplayObjectUtils.getTargetInComponentDisplayList(target, componentTree); |
| |
| |
| if (targetDescription) { |
| |
| // see the top of this document on how to generate source code |
| getAppliedPropertiesFromHistory(iDocument, targetDescription); |
| |
| if (!reference) { |
| //output = getHTMLOutputString(iDocument, iDocument.componentDescription); |
| |
| var includePreviewCode:Boolean = true; |
| var tabDepth:String = ""; |
| |
| if (showFullHTMLPageSource) { |
| tabDepth = ""; //"\t\t\t"; |
| } |
| |
| output = getHTMLOutputString(iDocument, targetDescription, true, tabDepth, includePreviewCode); |
| output += "\n"; |
| |
| var applicationContainerID:String = "applicationContainer"; |
| var zoomInID:String = wrapInPreview ? application.name : applicationContainerID; |
| |
| // not enabled at the moment - see code inspector |
| if (wrapInPreview) { |
| var wrapper:String = "<div id=\"" + applicationContainerID +"\" style=\"position:absolute;"; |
| //output += "width:" + (component.instance.width + 40) + "px;"; |
| wrapper += "width:100%;"; |
| wrapper += "height:" + (targetDescription.instance.height + 40) + "px;"; |
| wrapper += "background-color:#666666;\">\n" + output + "</div>"; |
| output = wrapper; |
| } |
| |
| if (stylesheets) { |
| output += "\n" + stylesheets; |
| } |
| |
| var styles:String = ""; |
| |
| if (showOnlyCSS) { |
| |
| // SPOT NUMBER 1 |
| // you have to include css options in another spot as well below |
| // SEE SPOT NUMBER 2 |
| // refactor |
| if (!useInlineStyles) { |
| styles = "\n" + cssOutput; |
| } |
| |
| if (css) { |
| styles += "\n" + css; |
| } |
| |
| if (useSVGButtonClass) { |
| styles += "\n" + buttonCSS2; |
| } |
| |
| if (showBorders) { |
| styles += "\n" + showBordersCSS; |
| } |
| |
| if (addZoom) { |
| //zoomOutput = zoomCSS.replace(/IFRAME_ID/g, "#" + application.name); |
| zoomOutput = zoomCSS.replace(/IFRAME_ID/g, "#" + zoomInID); |
| zoomOutput = zoomOutput.replace(/ZOOM_VALUE/g, iDocument.scale); |
| styles += "\n" + zoomOutput; |
| } |
| |
| output = styles; |
| } |
| else if (showOnlyHTML) { |
| |
| if (showFullHTMLPageSource) { |
| output = template.replace(contentToken, output); |
| } |
| } |
| else { |
| // THIS IS SPOT NUMBER 2 |
| // You have to include CSS options in another place as well |
| // see spot number 1 |
| if (!useInlineStyles) { |
| styles += "\n" + cssOutput; |
| } |
| |
| if (css) { |
| styles += "\n" + css; |
| } |
| |
| if (useSVGButtonClass) { |
| styles += "\n" + buttonCSS2; |
| } |
| |
| if (showBorders) { |
| styles += "\n" + showBordersCSS; |
| } |
| |
| |
| if (addZoom) { |
| //zoomOutput = zoomCSS.replace(/IFRAME_ID/g, "#" + application.name); |
| zoomOutput = zoomCSS.replace(/IFRAME_ID/g, "#" + zoomInID); |
| zoomOutput = zoomOutput.replace(/ZOOM_VALUE/g, iDocument.scale); |
| styles += "\n" + zoomOutput; |
| } |
| |
| |
| |
| |
| // add styles in style tags and add to output |
| if (styles!="") { |
| output += "\n" + wrapInStyleTags(styles); |
| } |
| |
| |
| |
| if (showFullHTMLPageSource) { |
| output = template.replace(contentToken, output); |
| } |
| } |
| |
| |
| isValid = XMLUtils.isValidXML(output); |
| |
| if (!isValid) { |
| error = XMLUtils.validationError; |
| errorMessage = XMLUtils.validationErrorMessage; |
| } |
| else { |
| error = null; |
| errorMessage = null; |
| } |
| |
| var checkValidXML:Boolean = false; |
| if (checkValidXML) { |
| try { |
| // don't use XML for HTML output because it converts this: |
| // <div ></div> |
| // to this: |
| // <div /> |
| // and that breaks the html page |
| |
| // we can still try it to make sure it's valid |
| // we could be saving CPU cycles here? |
| var time:int = getTimer(); |
| |
| // check if valid XML |
| // we could also use XMLUtils.isValid but this is also for formatting |
| xml = new XML(output); |
| time = getTimer() -time; |
| //trace("xml validation parsing time=" + time); |
| sourceCode = output; |
| } |
| catch (error:Error) { |
| // Error #1083: The prefix "s" for element "Group" is not bound. |
| // <s:Group x="93" y="128"> |
| // <s:Button x="66" y="17"/> |
| //</s:Group> |
| time = getTimer() -time; |
| //trace("xml validation parsing time with error=" + time); |
| sourceCode = output; |
| } |
| } |
| else { |
| sourceCode = output; |
| } |
| } |
| else {// this should not be here - it should be in DocumentData |
| XML1 = <document />; |
| XML1.@host = iDocument.host; |
| XML1.@id = iDocument.id; |
| XML1.@name = iDocument.name; |
| XML1.@uid = iDocument.uid; |
| XML1.@uri = iDocument.uri; |
| output = XML1.toXMLString(); |
| } |
| } |
| |
| return output; |
| } |
| |
| |
| |
| /** |
| * Gets the formatted output from a component. |
| * Yes, this is a mess. It needs refactoring. |
| * I wanted to see if I could quickly generate valid HTML |
| * from the component tree. |
| * |
| * There is partial work with CSS properties objects but those are not implemented yet. |
| * */ |
| public function getHTMLOutputString(iDocument:IDocument, component:ComponentDescription, addLineBreak:Boolean = false, tabs:String = "", includePreview:Boolean = false):String { |
| var property:Object = component.properties; |
| var componentName:String = component.name ? component.name.toLowerCase() : ""; |
| var htmlName:String = componentName ? componentName : ""; |
| var componentChild:ComponentDescription; |
| var contentToken:String = "[child_content]"; |
| var styleValue:String = "position:absolute;"; |
| var styles:Styles = new Styles(); |
| var wrapperStyles:Styles = new Styles(); |
| var isHorizontalLayout:Boolean; |
| var isVerticalLayout:Boolean; |
| var isBasicLayout:Boolean; |
| var isTileLayout:Boolean; |
| var childContent:String = ""; |
| var wrapperTag:String = ""; |
| var centeredHorizontally:Boolean; |
| var wrapperTagStyles:String = ""; |
| var properties:String = ""; |
| var outlineStyle:String; |
| var output:String = ""; |
| var type:String = ""; |
| var instance:Object; |
| var numElements:int; |
| var index:int; |
| var value:*; |
| var gap:int; |
| |
| |
| // we are setting the styles in a string now |
| // the next refactor should use the object so we can output to CSS |
| styles.position = Styles.ABSOLUTE; |
| outlineStyle = "outline:1px solid red;"; // we should enable or disable outlines via code not markup on in the export |
| |
| // get layout positioning |
| if (component.parent && component.parent.instance is IVisualElementContainer) { |
| |
| if (component.parent.instance.layout is HorizontalLayout) { |
| isHorizontalLayout = true; |
| styleValue = styleValue.replace("absolute", "relative"); |
| //styleValue += "vertical-align:middle;"; |
| styles.position = Styles.RELATIVE; |
| index = GroupBase(component.parent.instance).getElementIndex(component.instance as IVisualElement); |
| numElements = GroupBase(component.parent.instance).numElements; |
| wrapperTagStyles += hasExplicitSizeSet(component.instance as IVisualElement) ? "display:inline-block;" : "display:inline;"; |
| wrapperStyles.display = hasExplicitSizeSet(component.instance as IVisualElement) ? Styles.INLINE_BLOCK : Styles.INLINE; |
| gap = HorizontalLayout(component.parent.instance.layout).gap - 4; |
| |
| |
| if (index<numElements-1 && numElements>1) { |
| //wrapperTagStyles += "padding-right:" + gap + "px;"; |
| wrapperTagStyles += Styles.MARGIN_RIGHT+":" + gap + "px;"; |
| wrapperStyles.marginRight = gap + "px"; |
| |
| } |
| |
| wrapperTag = "div"; |
| } |
| else if (component.parent.instance.layout is TileLayout) { |
| //isHorizontalLayout = true; |
| isTileLayout = true; |
| styleValue = styleValue.replace("absolute", "relative"); |
| styles.position = Styles.RELATIVE; |
| index = GroupBase(component.parent.instance).getElementIndex(component.instance as IVisualElement); |
| numElements = GroupBase(component.parent.instance).numElements; |
| wrapperTagStyles += hasExplicitSizeSet(component.instance as IVisualElement) ? "display:inline-block;" : "display:inline;"; |
| wrapperStyles.display = hasExplicitSizeSet(component.instance as IVisualElement) ? Styles.INLINE_BLOCK : Styles.INLINE; |
| gap = TileLayout(component.parent.instance.layout).horizontalGap - 4; |
| |
| if (index<numElements-1 && numElements>1) { |
| //wrapperTagStyles += "padding-right:" + gap + "px;"; |
| // using "margin-right" because if you set a fixed width padding was not doing anything |
| wrapperTagStyles += Styles.MARGIN_RIGHT+":" + gap + "px;"; |
| //wrapperStyles.paddingRight = gap + "px"; |
| wrapperStyles.marginRight = gap + "px"; |
| } |
| |
| wrapperTag = "div"; |
| } |
| |
| else if (component.parent.instance.layout is VerticalLayout) { |
| isVerticalLayout = true; |
| styleValue = styleValue.replace("absolute", "relative"); |
| styles.position = Styles.RELATIVE; |
| index = GroupBase(component.parent.instance).getElementIndex(component.instance as IVisualElement); |
| numElements = GroupBase(component.parent.instance).numElements; |
| gap = VerticalLayout(component.parent.instance.layout).gap; |
| |
| |
| if (index<numElements-1 && numElements>1) { |
| //wrapperTagStyles += "padding-bottom:" + gap + "px;"; |
| wrapperTagStyles += Styles.MARGIN_BOTTOM+":" + gap + "px;"; |
| //wrapperStyles.paddingBottom = gap + "px"; |
| wrapperStyles.marginBottom = gap + "px"; |
| } |
| |
| wrapperTag = "div"; |
| } |
| |
| else if (component.parent.instance.layout is BasicLayout) { |
| isBasicLayout = true; |
| |
| |
| |
| //styleValue = styleValue.replace("absolute", "relative"); |
| //styles.position = Styles.RELATIVE; |
| /*index = GroupBase(component.parent.instance).getElementIndex(component.instance as IVisualElement); |
| numElements = GroupBase(component.parent.instance).numElements; |
| gap = BasicLayout(component.parent.instance.layout).gap;*/ |
| |
| /*if (index<numElements-1 && numElements>1) { |
| wrapperTagStyles += "padding-bottom:" + gap + "px"; |
| } |
| |
| wrapperTag = "div";*/ |
| } |
| } |
| |
| // constraints take higher authority |
| var isHorizontalSet:Boolean; |
| var isVerticalSet:Boolean; |
| |
| // loop through assigned properties |
| for (var propertyName:String in property) { |
| value = property[propertyName]; |
| |
| if (value===undefined || value==null) { |
| continue; |
| } |
| |
| |
| if (verticalPositions.indexOf(propertyName)!=-1 && !isVerticalSet) { |
| styleValue = getVerticalPositionHTML(component.instance as IVisualElement, styles, styleValue, isBasicLayout); |
| isVerticalSet = true; |
| } |
| else if (horizontalPositions.indexOf(propertyName)!=-1 && !isHorizontalSet) { |
| styleValue = getHorizontalPositionHTML(component.instance as IVisualElement, styles, styleValue, isBasicLayout); |
| isHorizontalSet = true; |
| } |
| |
| } |
| |
| |
| if (htmlName) { |
| |
| // create code for element type |
| if (htmlName=="application") { |
| htmlName = "div"; |
| |
| // container div |
| if (includePreview) { |
| /*output = "<div style=\"position:absolute;"; |
| //output += "width:" + (component.instance.width + 40) + "px;"; |
| output += "width:100%;"; |
| output += "height:" + (component.instance.height + 40) + "px;"; |
| output += "background-color:#666666;\">";*/ |
| output += "<div"; |
| //output = getNameString(component.instance, output); |
| output += properties ? " " + properties : " "; |
| output = getIdentifierAttribute(component.instance, output); |
| styleValue = styleValue.replace("absolute", "relative"); |
| styles.position = Styles.ABSOLUTE; |
| styleValue += "width:" + component.instance.width+ "px;"; |
| styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| styleValue += "margin:0 auto;"; |
| styleValue += "left:8px;top:14px;"; |
| styleValue += "overflow:auto;"; |
| styleValue += "background-color:" + DisplayObjectUtils.getColorInHex(component.instance.getStyle("backgroundColor"), true) + ";"; |
| //output += properties ? " " : ""; |
| output += setStyles(component.instance, styleValue); |
| |
| |
| if (showScreenshotBackground) { |
| var backgroundImageID:String = "backgroundComparisonImage"; |
| var imageDataFormat:String = "png";//"jpeg"; |
| var imageData:String = getDataURI(component.instance, imageDataFormat); |
| var backgroundSnapshot:String = "\n" + tabs + "\t" + "<img "; |
| backgroundSnapshot += "id=\"" + backgroundImageID +"\""; |
| backgroundSnapshot += " src=\"" + imageData + "\" "; |
| |
| output += backgroundSnapshot; |
| output += setStyles("#"+backgroundImageID, "position:absolute;opacity:"+backgroundImageAlpha+";top:0px;left:0px;", true); |
| /* background-image didn't work in FF on mac. didn't test on other browsers |
| //trace(imageData); |
| var imageDataStyle:String = "#" + getIdentifierOrName(target) + " {\n"; |
| //imageDataStyle = "\tbackground-image: url(data:image/jpeg;base64,"+imageData+");"; |
| imageDataStyle += "\tbackground-repeat: no-repeat;\n"; |
| imageDataStyle += "\tbackground-image: url(data:image/"+imageDataFormat+";base64,"+imageData+");\n}"; |
| styles += "\n" + imageDataStyle;*/ |
| } |
| |
| output += contentToken; |
| //output += "\n </div>\n</div>"; |
| output += "\n</div>"; |
| |
| } |
| else { |
| //output = "<div style=\"position: absolute;width:100%;height:100%;background-color:#666666;\">"; |
| output = "<div"; |
| output += properties ? " " + properties : " "; |
| output = getIdentifierAttribute(component.instance, output); |
| //output = getNameString(component.instance, output); |
| output += properties ? " " + properties : ""; |
| styleValue += "width:" + component.instance.width+ "px;"; |
| styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue += "border:1px solid black"; |
| styleValue += "background-color:" + DisplayObjectUtils.getColorInHex(component.instance.getStyle("backgroundColor"), true) + ";"; |
| //output += properties ? " " : ""; |
| output += setStyles(component.instance, styleValue); |
| output += contentToken; |
| output += "\n</div>"; |
| } |
| } |
| |
| else if (htmlName=="group" || htmlName=="vgroup") { |
| htmlName = "div"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<div " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| output += properties ? " " : ""; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| |
| //styleValue += "width:" + component.instance.width+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| output += setStyles(component.instance, styleValue); |
| output += contentToken; |
| output += "\n" + tabs + "</div>"; |
| output += getWrapperTag(wrapperTag, true); |
| } |
| |
| else if (htmlName=="bordercontainer") { |
| htmlName = "div"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<div " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| output += properties ? " " : ""; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| styleValue += getBorderString(component.instance as BorderContainer); |
| //styleValue += getColorString(component.instance as BorderContainer); |
| //styles += component.instance as BorderContainer); |
| |
| output += setStyles(component.instance, styleValue); |
| output += contentToken; |
| output += "\n" + tabs + "</div>"; |
| output += getWrapperTag(wrapperTag, true); |
| |
| } |
| |
| else if (htmlName=="hgroup" || htmlName=="tilegroup") { |
| htmlName = "div"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<div " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| |
| //styleValue = getSizeString(component.instance as IVisualElement, styleValue); |
| if (component.name=="HGroup") { |
| styleValue += "width:" + Math.max(HGroup(component.instance).contentWidth, component.instance.width)+ "px;"; |
| } |
| else { |
| styleValue += "width:" + component.instance.width+ "px;"; |
| } |
| |
| styleValue += "height:" + component.instance.height+ "px;"; |
| //var verical:String = component.instance.getStyle("verticalAlign"); |
| var vericalAlign:String = component.instance.verticalAlign; |
| if (componentName.toLowerCase()=="hgroup" && vericalAlign=="middle") { |
| styleValue += "line-height:" + component.instance.height + "px;"; |
| } |
| |
| output += properties ? " " : ""; |
| output += setStyles(component.instance, styleValue); |
| output += contentToken; |
| output += "\n" + tabs + "</div>"; |
| output += getWrapperTag(wrapperTag, true); |
| } |
| else if (htmlName=="button" || htmlName=="togglebutton") { |
| htmlName = "button"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<input " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| output += " type=\"" + htmlName.toLowerCase() + "\"" ; |
| output += properties ? " " + properties : ""; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| output += " value=\"" + component.instance.label + "\""; |
| output += " class=\"buttonSkin\""; |
| output += setStyles(component.instance, styleValue); |
| |
| output += getWrapperTag(wrapperTag, true); |
| } |
| else if (htmlName=="checkbox") { |
| if (component.instance.label!="") { |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<label "; |
| output = getIdentifierAttribute(component.instance, output, "_Label"); |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| //styleValue += "width:" + (component.instance.width + 6)+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| output += setStyles("#"+getIdentifierOrName(component.instance, true, "_Label"), styleValue); |
| output += "<input "; |
| output = getIdentifierAttribute(component.instance, output); |
| output += " type=\"" + htmlName.toLowerCase() + "\" "; |
| output += "/>" ; |
| } |
| else { |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<input " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| output += " type=\"" + htmlName.toLowerCase() + "\" " + properties; |
| //styleValue = getSizeString(component.instance as IVisualElement, styleValue); |
| output += setStyles(component.instance, styleValue); |
| } |
| |
| if (component.instance.label!="") { |
| output += " " + component.instance.label + "</label>"; |
| } |
| |
| output += getWrapperTag(wrapperTag, true); |
| } |
| else if (htmlName=="radiobutton") { |
| htmlName = "radio"; |
| if (component.instance.label!="") { |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<label "; |
| output = getIdentifierAttribute(component.instance, output, "_Label"); |
| //styleValue += "width:" + (component.instance.width + 8)+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| output += setStyles("#"+getIdentifierOrName(component.instance, true, "_Label"), styleValue); |
| output += "<input type=\"radio\" " ; |
| output = getIdentifierAttribute(component.instance, output); |
| //styleValue = getSizeString(component.instance as IVisualElement, styleValue); |
| output += "/>" ; |
| } |
| else { |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<input type=\"" + htmlName.toLowerCase() + "\" " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| //styleValue = getSizeString(component.instance as IVisualElement, styleValue); |
| output += setStyles(component.instance, styleValue); |
| } |
| |
| if (component.instance.label!="") { |
| output += " " + component.instance.label + "</label>"; |
| } |
| |
| output += getWrapperTag(wrapperTag, true); |
| } |
| else if (htmlName=="textinput" || htmlName=="combobox") { |
| htmlName = "input"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<input "; |
| output = getIdentifierAttribute(component.instance, output); |
| output += " type=\"input\" " + properties; |
| //styleValue += "width:" + component.instance.width+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| styleValue += "padding:0;border:1px solid " + DisplayObjectUtils.getColorInHex(component.instance.getStyle("borderColor"), true) + ";"; |
| |
| if (htmlName=="combobox") { |
| output += " list=\"listdata\""; |
| //<datalist id="listData"> |
| //<option value="value 1"> |
| //<option value="value 2"> |
| //<option value="value 3"> |
| //</datalist> |
| } |
| output += setStyles(component.instance, styleValue); |
| output += getWrapperTag(wrapperTag, true); |
| } |
| else if (htmlName=="dropdownlist") { |
| htmlName = "select"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<select "; |
| output = getIdentifierAttribute(component.instance, output); |
| output += " type=\"input\" " + properties; |
| //styleValue += "width:" + component.instance.width+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| styleValue += "padding:0;border:1px solid " + DisplayObjectUtils.getColorInHex(component.instance.getStyle("borderColor"), true) + ";"; |
| |
| output += setStyles(component.instance, styleValue); |
| output += "</select>"; |
| output += getWrapperTag(wrapperTag, true); |
| } |
| else if (htmlName=="linkbutton") { |
| htmlName = "a"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<a " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| //styleValue += "width:" + component.instance.width+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| //styles += getBorderString(component.instance as IStyleClient); |
| |
| output += properties ? " " : ""; |
| output += setStyles(component.instance, styleValue); |
| output += component.instance.label; |
| output += "</a>"; |
| output += getWrapperTag(wrapperTag, true); |
| } |
| else if (htmlName=="label") { |
| htmlName = "label"; |
| if (useWrapperDivs) { |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| } |
| else { |
| output = tabs; |
| } |
| output += "<label " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| //styleValue += "width:" + component.instance.width+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet, isVerticalSet); |
| //styleValue += wrapperTagStyles; |
| styleValue += "color:" + DisplayObjectUtils.getColorInHex(component.instance.getStyle("color"), true) + ";"; |
| styleValue += "font-weight:" + component.instance.getStyle("fontWeight") + ";"; |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| styleValue += "line-height:" + "1;"; |
| //styles += getBorderString(component.instance as IStyleClient); |
| |
| output += properties ? " " : ""; |
| // remove wrapperTagStyles since we are trying to not use wrapper tags |
| //output += setStyles(component.instance, styleValue+wrapperTagStyles); |
| output += setStyles(component.instance, wrapperTagStyles+styleValue); |
| output += component.instance.text; |
| output += "</label>"; |
| if (useWrapperDivs) { |
| output += getWrapperTag(wrapperTag, true); |
| } |
| } |
| else if (htmlName=="image") { |
| htmlName = "img"; |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<img " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| //styleValue += "width:" + component.instance.width+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| output += properties ? " " : ""; |
| |
| if (component.instance.source is BitmapData) { |
| output += " src=\"" + getDataURI(component.instance.source, "jpeg") + "\""; |
| } |
| else if (component.instance.source is String) { |
| output += " src=\"" + component.instance.source + "\""; |
| } |
| output += setStyles(component.instance, styleValue); |
| output += getWrapperTag(wrapperTag, true); |
| } |
| |
| else { |
| // show placeholder NOT actual component |
| htmlName = "label"; |
| if (useWrapperDivs) { |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| } |
| else { |
| output = tabs; |
| } |
| output += "<label " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| //styleValue += "width:" + component.instance.width+ "px;"; |
| //styleValue += "height:" + component.instance.height+ "px;"; |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet, isVerticalSet); |
| //styleValue += wrapperTagStyles; |
| styleValue += "color:" + DisplayObjectUtils.getColorInHex(component.instance.getStyle("color"), true) + ";"; |
| styleValue += "font-weight:" + component.instance.getStyle("fontWeight") + ";"; |
| styleValue += "font-family:" + component.instance.getStyle("fontFamily") + ";"; |
| styleValue += "font-size:" + component.instance.getStyle("fontSize") + "px;"; |
| styleValue += "line-height:" + "1;"; |
| //styles += getBorderString(component.instance as IStyleClient); |
| |
| output += properties ? " " : ""; |
| // remove wrapperTagStyles since we are trying to not use wrapper tags |
| //output += setStyles(component.instance, styleValue+wrapperTagStyles); |
| output += setStyles(component.instance, wrapperTagStyles+styleValue); |
| output += getIdentifierOrName(component.instance); |
| output += "</label>"; |
| if (useWrapperDivs) { |
| output += getWrapperTag(wrapperTag, true); |
| } |
| /* |
| output = tabs + getWrapperTag(wrapperTag, false, wrapperTagStyles); |
| output += "<" + htmlName.toLowerCase() + " " + properties; |
| output = getIdentifierAttribute(component.instance, output); |
| styleValue = getSizeString(component.instance as IVisualElement, styleValue, isHorizontalSet); |
| output += properties ? " " : ""; |
| output += setStyles(component.instance, styleValue); |
| output += getWrapperTag(wrapperTag, true);*/ |
| } |
| |
| |
| // add children |
| if (component.children && component.children.length>0) { |
| //output += ">\n"; |
| |
| for (var i:int;i<component.children.length;i++) { |
| componentChild = component.children[i]; |
| getAppliedPropertiesFromHistory(iDocument, componentChild); |
| if (i>0) { |
| childContent += "\n"; |
| } |
| childContent += getHTMLOutputString(iDocument, componentChild, false, tabs + "\t"); |
| } |
| |
| output = output.replace(contentToken, "\n" + childContent); |
| |
| } |
| else { |
| output = output.replace(contentToken, "\n"); |
| } |
| } |
| else { |
| output = ""; |
| } |
| |
| return output; |
| } |
| |
| /** |
| * Get a tag with less than or greater than wrapped around it. |
| * */ |
| private function getWrapperTag(wrapperTag:String = "", end:Boolean = false, styles:String = ""):String { |
| var output:String = ""; |
| |
| if (wrapperTag=="") return ""; |
| |
| if (end) { |
| output = "</" + wrapperTag + ">"; |
| return output; |
| } |
| |
| output += "<" + wrapperTag; |
| |
| if (styles) { |
| output += " style=\"" + styles + "\"" ; |
| } |
| |
| output += ">"; |
| |
| return output; |
| } |
| |
| /** |
| * Get width and height styles |
| * If explicit width is set then we should use inline-block |
| * because inline does not respect width and height |
| * */ |
| public function getSizeString(instance:IVisualElement, styleValue:String = "", isHorizontalAlignSet:Boolean = false, isVerticalSet:Boolean = false):String { |
| var hasExplicitSize:Boolean; |
| var hasBorder:Boolean; |
| var border:int; |
| |
| if (instance is IStyleClient && IStyleClient(instance).getStyle("borderWeight")) { |
| |
| } |
| |
| if (!isNaN(instance.percentWidth)) { |
| styleValue += "width:" + instance.percentWidth + "%;"; |
| } |
| else if ("explicitWidth" in instance) { |
| if (Object(instance).explicitWidth!=null && !isNaN(Object(instance).explicitWidth) |
| || setExplicitSize) { |
| styleValue += "width:" + instance.width + "px;"; |
| hasExplicitSize = true; |
| } |
| } |
| else { |
| //styleValue += "width:" + instance.width + "px;"; |
| } |
| |
| if (!isNaN(instance.percentHeight)) { |
| styleValue += "height:" + instance.percentHeight + "%;"; |
| } |
| else if ("explicitHeight" in instance) { |
| if (Object(instance).explicitHeight!=null && !isNaN(Object(instance).explicitHeight) |
| || setExplicitSize) { |
| styleValue += "height:" + instance.height + "px;"; |
| hasExplicitSize = true; |
| } |
| } |
| else { |
| //styleValue += "height:" + instance.height + "px;"; |
| } |
| |
| |
| // If explicit width is set then we should use inline-block |
| // because inline does not respect width and height |
| if (!isHorizontalAlignSet && hasExplicitSize) { |
| styleValue += "display:" + Styles.INLINE_BLOCK + ";"; |
| } |
| |
| return styleValue; |
| |
| } |
| |
| /** |
| * Checks if size is explicitly set |
| * If explicit width is set then we should use inline-block |
| * because inline does not respect width and height |
| * */ |
| public function hasExplicitSizeSet(instance:IVisualElement):Boolean { |
| |
| if ("explicitWidth" in instance && Object(instance).explicitWidth!=null) { |
| return true; |
| } |
| else if ("explicitHeight" in instance && Object(instance).explicitHeight!=null) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Get the horizontal position string for HTML |
| * */ |
| public function getHorizontalPositionHTML(instance:IVisualElement, propertyModel:Styles, stylesValue:String = "", isBasicLayout:Boolean = true):String { |
| |
| if (!isBasicLayout) return stylesValue; |
| // horizontal center trumps left and x properties |
| if (instance.horizontalCenter!=null) { |
| stylesValue += "display:block;margin:" + instance.horizontalCenter + " auto;left:0;right:0;"; |
| //stylesValue = stylesValue.replace("absolute", "relative"); |
| |
| propertyModel.display = Styles.BLOCK; |
| //propertyModel.position = Styles.RELATIVE; |
| propertyModel.position = Styles.ABSOLUTE; |
| propertyModel.margin = instance.horizontalCenter + " auto;left:0;right:0;"; |
| |
| return stylesValue; |
| } |
| else if (instance.left!=null || instance.right!=null) { |
| stylesValue += instance.left!=null ? "left:" + instance.left + "px;" : ""; |
| stylesValue += instance.right!=null ? "right:" + instance.right + "px;" : ""; |
| if (instance.left!=null) propertyModel.left = instance.left + "px"; |
| if (instance.right!=null) propertyModel.right = instance.right + "px"; |
| return stylesValue; |
| } |
| else { |
| stylesValue += "left:" + instance.x + "px;"; |
| propertyModel.left = instance.x + "px;"; |
| } |
| |
| return stylesValue; |
| } |
| |
| |
| /** |
| * Get the vertical position string for HTML |
| * */ |
| public function getVerticalPositionHTML(instance:IVisualElement, propertyModel:Styles, stylesValue:String = "", isBasicLayout:Boolean = true):String { |
| |
| if (!isBasicLayout) return stylesValue; |
| |
| if (instance.verticalCenter!=null) { |
| stylesValue += "display:block;margin:" + instance.verticalCenter + " auto;"; |
| stylesValue = stylesValue.replace("absolute", "relative"); |
| |
| propertyModel.display = Styles.BLOCK; |
| propertyModel.position = Styles.RELATIVE; |
| propertyModel.margin = instance.verticalCenter + " auto;"; |
| |
| return stylesValue; |
| } |
| else if (instance.top!=null || instance.bottom!=null) { |
| stylesValue += instance.top!=null ? "top:" + instance.top + "px;" : ""; |
| stylesValue += instance.bottom!=null ? "bottom:" + instance.bottom + "px;" : ""; |
| if (instance.top!=null) propertyModel.top = instance.top + "px"; |
| if (instance.bottom!=null) propertyModel.bottom = instance.bottom + "px"; |
| return stylesValue; |
| } |
| else { |
| stylesValue += "top:" + instance.y + "px;"; |
| propertyModel.top = instance.y + "px;"; |
| } |
| |
| return stylesValue; |
| } |
| |
| /** |
| * Get border and background styles of a border container |
| * */ |
| public function getBorderString(element:IStyleClient):String { |
| var value:String = ""; |
| |
| if (element.getStyle("backgroundAlpha")!=0) { |
| value += "background-color:" + DisplayObjectUtils.getColorInHex(element.getStyle("backgroundColor"), true) + ";"; |
| value += "background-alpha:" + element.getStyle("backgroundAlpha") + ";"; |
| } |
| |
| if (element.getStyle("borderVisible")) { |
| value += "border-width:" + element.getStyle("borderWeight") + "px;"; |
| value += "border-style:solid;"; |
| |
| if (element.getStyle("borderColor")!==undefined) { |
| value += "border-color:" + DisplayObjectUtils.getColorInHex(element.getStyle("borderColor"), true) + ";"; |
| } |
| } |
| |
| if (element.getStyle("color")!==undefined) { |
| value += "color:" + DisplayObjectUtils.getColorInHex(element.getStyle("color"), true) + ";"; |
| } |
| |
| return value; |
| } |
| |
| /** |
| * Set styles |
| * */ |
| public function setStyles(component:Object, styles:String = "", singleton:Boolean = false):String { |
| var out:String = ">"; |
| |
| if (useInlineStyles) { |
| return " style=\"" + styles + "\"" + (singleton?"\>":">"); |
| } |
| else { |
| var formatted:String= "\t" + styles.replace(/;/g, ";\n\t"); |
| |
| //styles += ";"; |
| //cssOutput += "#" + getIdentifierOrName(component) + " {\n\n"; |
| //cssOutput += "" + styles.replace(/;/g, ";\n") + "\n\n} "; |
| |
| if (component is String) { |
| out = component + " {\n"; |
| } |
| else { |
| out = "#" + getIdentifierOrName(component) + " {\n"; |
| } |
| out += formatted; |
| out += "}\n\n"; |
| |
| out = out.replace(/\t}/g, "}"); |
| |
| cssOutput += out; |
| } |
| |
| return (singleton?"\>":">"); |
| } |
| |
| |
| /** |
| * Wrap in style tags |
| * */ |
| public function wrapInStyleTags(value:String):String { |
| var out:String = "<style>\n" + value + "\n</style>"; |
| return out; |
| } |
| |
| /** |
| * Gets the ID of the target object |
| * |
| * @param name if id is not available then if the name parameter is true then use name |
| * |
| * returns id or name |
| * */ |
| public function getIdentifierOrName(element:Object, name:Boolean = true, appendID:String = ""):String { |
| |
| if (element && "id" in element && element.id) { |
| return element.id + appendID; |
| } |
| else if (element && name && "name" in element && element.name) { |
| return element.name + appendID; |
| } |
| |
| return ""; |
| } |
| |
| /** |
| * Get ID from ID or else name attribute |
| * */ |
| public function getIdentifierAttribute(instance:Object, value:String = "", appendID:String = ""):String { |
| |
| if (instance && "id" in instance && instance.id) { |
| value += "id=\"" + instance.id + appendID + "\""; |
| } |
| |
| else if (instance && "name" in instance && instance.name) { |
| value += "id=\"" + instance.name + appendID + "\""; |
| } |
| |
| return value; |
| } |
| |
| /** |
| * Get name and ID attribute |
| * */ |
| public function getIdentifierOrNameAttribute(instance:Object, propertyValue:String = ""):String { |
| |
| if (instance && "id" in instance && instance.id) { |
| propertyValue += "id=\"" + instance.id + "\""; |
| } |
| |
| if (instance && "name" in instance && instance.name) { |
| propertyValue += "name=\"" + instance.name + "\""; |
| } |
| |
| return propertyValue; |
| } |
| |
| /** |
| * @inheritDoc |
| * */ |
| public function exportXML(document:IDocument, reference:Boolean = false):XML { |
| return null; |
| } |
| |
| /** |
| * @inheritDoc |
| * */ |
| public function exportJSON(document:IDocument, reference:Boolean = false):JSON { |
| return null; |
| } |
| |
| /** |
| * Get data URI from object. |
| * |
| * Encoding to JPG took 2000ms in some cases where PNG took 200ms. |
| * I have not extensively tested this but it seems to be 10x faster |
| * than JPG. |
| * */ |
| public function getDataURI(target:Object, type:String = "png"):String { |
| var output:String; |
| |
| if (type.toLowerCase()=="jpg") { |
| type = "jpeg"; |
| } |
| |
| output = "data:image/" + type + ";base64," + getBase64ImageData(target, type); |
| |
| return output; |
| } |
| |
| /** |
| * Returns base64 image string. |
| * |
| * Encoding to JPG took 2000ms in some cases where PNG took 200ms. |
| * I have not extensively tested this but it seems to be 10x faster |
| * than JPG. |
| * |
| * Performance: |
| * get snapshot. time=14 |
| * encode to png. time=336 // encode to jpg. time=2000 |
| * encode to base 64. time=35 |
| * |
| * Don't trust these numbers. Test it yourself. First runs are always longer than previous. |
| * |
| * This function gets called multiple times sometimes. We may be encoding more than we have too. |
| * But is probably a bug somewhere. |
| * */ |
| public function getBase64ImageData(target:Object, type:String = "png", checkCache:Boolean = false):String { |
| var component:IUIComponent = target as IUIComponent; |
| var bitmapData:BitmapData; |
| var byteArray:ByteArray; |
| var base64Encoder:Base64Encoder; |
| var base64Encoder2:Base64; |
| var useEncoder:Boolean; |
| var rectangle:Rectangle; |
| var jpegEncoderOptions:JPEGEncoderOptions; |
| var pngEncoderOptions:PNGEncoderOptions; |
| var quality:int = 80; |
| var fastCompression:Boolean = true; |
| var timeEvents:Boolean = false; |
| var altBase64:Boolean = true; |
| var results:String; |
| |
| |
| if (base64BitmapCache[target] && checkCache) { |
| return base64BitmapCache[target]; |
| } |
| |
| if (timeEvents) { |
| var time:int = getTimer(); |
| } |
| |
| if (component) { |
| bitmapData = BitmapUtil.getSnapshot(component); |
| } |
| else if (target is DisplayObject) { |
| bitmapData = DisplayObjectUtils.getBitmapDataSnapshot2(target as DisplayObject); |
| } |
| else if (target is BitmapData) { |
| bitmapData = target as BitmapData; |
| } |
| else { |
| return null; |
| } |
| |
| rectangle = new Rectangle(0, 0, bitmapData.width, bitmapData.height); |
| |
| if (timeEvents) { |
| trace ("get snapshot. time=" + (getTimer()-time)); |
| time = getTimer(); |
| } |
| |
| if (type=="png") { |
| |
| if (useEncoder) { |
| if (!pngEncoder) { |
| pngEncoder = new PNGEncoder(); |
| } |
| |
| byteArray = pngEncoder.encode(bitmapData); |
| } |
| else { |
| if (!pngEncoderOptions) { |
| pngEncoderOptions = new PNGEncoderOptions(fastCompression); |
| } |
| |
| byteArray = bitmapData.encode(rectangle, pngEncoderOptions); |
| } |
| } |
| else if (type=="jpg" || type=="jpeg") { |
| |
| if (useEncoder) { |
| if (!jpegEncoder) { |
| jpegEncoder = new JPEGEncoder(); |
| } |
| |
| byteArray = jpegEncoder.encode(bitmapData); |
| } |
| else { |
| if (!jpegEncoderOptions) { |
| jpegEncoderOptions = new JPEGEncoderOptions(quality); |
| } |
| |
| byteArray = bitmapData.encode(rectangle, jpegEncoderOptions); |
| } |
| } |
| else { |
| // raw bitmap image data |
| byteArray = bitmapData.getPixels(new Rectangle(0, 0, bitmapData.width, bitmapData.height)); |
| } |
| |
| if (timeEvents) { |
| trace ("encode to " + type + ". time=" + (getTimer()-time)); |
| time = getTimer(); |
| } |
| |
| if (!altBase64) { |
| if (!base64Encoder) { |
| base64Encoder = new Base64Encoder(); |
| } |
| |
| base64Encoder.encodeBytes(byteArray); |
| |
| results = base64Encoder.toString(); |
| } |
| else { |
| results = Base64.encode(byteArray); |
| } |
| |
| //trace(base64.toString()); |
| |
| if (timeEvents) { |
| trace ("encode to base 64. time=" + (getTimer()-time)); |
| } |
| |
| base64BitmapCache[target] = results; |
| |
| return results; |
| } |
| |
| public var base64BitmapCache:Dictionary = new Dictionary(true) |
| } |
| } |