/* * JSwiff is an open source Java API for Macromedia Flash file generation * and manipulation * * Copyright (C) 2004-2006 Ralf Terdic (contact@jswiff.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.jswiff.xml; import com.jswiff.swfrecords.AlignmentZone; import com.jswiff.swfrecords.AlphaBitmapData; import com.jswiff.swfrecords.AlphaColorMapData; import com.jswiff.swfrecords.BevelFilter; import com.jswiff.swfrecords.BitmapData; import com.jswiff.swfrecords.BitmapPixelData; import com.jswiff.swfrecords.BlendMode; import com.jswiff.swfrecords.BlurFilter; import com.jswiff.swfrecords.ButtonCondAction; import com.jswiff.swfrecords.ButtonRecord; import com.jswiff.swfrecords.CXform; import com.jswiff.swfrecords.CXformWithAlpha; import com.jswiff.swfrecords.ClipActionRecord; import com.jswiff.swfrecords.ClipActions; import com.jswiff.swfrecords.ClipEventFlags; import com.jswiff.swfrecords.Color; import com.jswiff.swfrecords.ColorMapData; import com.jswiff.swfrecords.ColorMatrixFilter; import com.jswiff.swfrecords.ConvolutionFilter; import com.jswiff.swfrecords.CurvedEdgeRecord; import com.jswiff.swfrecords.DropShadowFilter; import com.jswiff.swfrecords.EnhancedStrokeStyle; import com.jswiff.swfrecords.FillStyle; import com.jswiff.swfrecords.FillStyleArray; import com.jswiff.swfrecords.FocalGradient; import com.jswiff.swfrecords.FocalMorphGradient; import com.jswiff.swfrecords.GlowFilter; import com.jswiff.swfrecords.GlyphEntry; import com.jswiff.swfrecords.GradRecord; import com.jswiff.swfrecords.Gradient; import com.jswiff.swfrecords.GradientBevelFilter; import com.jswiff.swfrecords.GradientGlowFilter; import com.jswiff.swfrecords.LineStyle; import com.jswiff.swfrecords.LineStyle2; import com.jswiff.swfrecords.LineStyleArray; import com.jswiff.swfrecords.Matrix; import com.jswiff.swfrecords.MorphFillStyle; import com.jswiff.swfrecords.MorphFillStyles; import com.jswiff.swfrecords.MorphGradRecord; import com.jswiff.swfrecords.MorphGradient; import com.jswiff.swfrecords.MorphLineStyle; import com.jswiff.swfrecords.MorphLineStyle2; import com.jswiff.swfrecords.MorphLineStyles; import com.jswiff.swfrecords.Pix15; import com.jswiff.swfrecords.Pix24; import com.jswiff.swfrecords.RGB; import com.jswiff.swfrecords.RGBA; import com.jswiff.swfrecords.Rect; import com.jswiff.swfrecords.Shape; import com.jswiff.swfrecords.ShapeRecord; import com.jswiff.swfrecords.ShapeWithStyle; import com.jswiff.swfrecords.SoundEnvelope; import com.jswiff.swfrecords.SoundInfo; import com.jswiff.swfrecords.StraightEdgeRecord; import com.jswiff.swfrecords.StyleChangeRecord; import com.jswiff.swfrecords.TextRecord; import com.jswiff.swfrecords.ZlibBitmapData; import com.jswiff.swfrecords.actions.Action; import com.jswiff.swfrecords.actions.ActionBlockReader; import com.jswiff.util.Base64; import com.jswiff.util.StringUtilities; import org.dom4j.Element; import java.util.Iterator; import java.util.List; /* * Writes SWF records (everything that's neither a tag nor an action) to XML. */ class RecordXMLWriter { static void writeActionBlock(Element parentElement, ActionBlockReader actionBlock) { List actions = actionBlock.getActions(); Element element = parentElement.addElement("actionblock"); for (Iterator it = actions.iterator(); it.hasNext();) { Action action = (Action) it.next(); ActionXMLWriter.writeAction(element, action); } } static void writeAlignmentZones( Element parentElement, AlignmentZone[] alignmentZones) { Element element = parentElement.addElement("zones"); for (int i = 0; i < alignmentZones.length; i++) { AlignmentZone zone = alignmentZones[i]; Element zoneElement = element.addElement("zone"); if (zone.hasX()) { zoneElement.addAttribute( "left", StringUtilities.doubleToString(zone.getLeft())); zoneElement.addAttribute( "width", StringUtilities.doubleToString(zone.getWidth())); } if (zone.hasY()) { zoneElement.addAttribute( "baseline", StringUtilities.doubleToString(zone.getBaseline())); zoneElement.addAttribute( "height", StringUtilities.doubleToString(zone.getHeight())); } } } static void writeButtonCondAction( Element parentElement, ButtonCondAction buttonCondAction) { Element element = parentElement.addElement("buttoncondaction"); if (buttonCondAction.isOutDownToIdle()) { element.addAttribute("outdowntoidle", "true"); } if (buttonCondAction.isOutDownToOverDown()) { element.addAttribute("outdowntooverdown", "true"); } if (buttonCondAction.isIdleToOverDown()) { element.addAttribute("idletooverdown", "true"); } if (buttonCondAction.isIdleToOverUp()) { element.addAttribute("idletooverup", "true"); } if (buttonCondAction.isOverDownToIdle()) { element.addAttribute("overdowntoidle", "true"); } if (buttonCondAction.isOverDownToOutDown()) { element.addAttribute("overdowntooutdown", "true"); } if (buttonCondAction.isOverDownToOverUp()) { element.addAttribute("overdowntooverup", "true"); } if (buttonCondAction.isOverUpToIdle()) { element.addAttribute("overuptoidle", "true"); } if (buttonCondAction.isOverUpToOverDown()) { element.addAttribute("overuptooverdown", "true"); } byte keyPress = buttonCondAction.getKeyPress(); if (keyPress != 0) { element.addAttribute("keypress", Byte.toString(keyPress)); } RecordXMLWriter.writeActionBlock(element, buttonCondAction.getActions()); } static void writeButtonRecord( Element parentElement, ButtonRecord buttonRecord) { Element element = parentElement.addElement("buttonrecord"); element.addAttribute( "charid", Integer.toString(buttonRecord.getCharacterId())); element.addAttribute( "depth", Integer.toString(buttonRecord.getPlaceDepth())); if (buttonRecord.hasBlendMode()) { element.addAttribute( "blendmode", BlendMode.getDescription(buttonRecord.getBlendMode())); } Element state = element.addElement("state"); if (buttonRecord.isUpState()) { state.addAttribute("up", "true"); } if (buttonRecord.isDownState()) { state.addAttribute("down", "true"); } if (buttonRecord.isOverState()) { state.addAttribute("over", "true"); } if (buttonRecord.isHitState()) { state.addAttribute("hit", "true"); } writeMatrix(element, buttonRecord.getPlaceMatrix()); CXformWithAlpha colorTransform = buttonRecord.getColorTransform(); if (colorTransform != null) { writeCXFormWithAlpha(element, colorTransform); } if (buttonRecord.hasFilters()) { RecordXMLWriter.writeFilters(element, buttonRecord.getFilters()); } } static void writeCXForm(Element parentElement, CXform cXform) { Element element = parentElement.addElement("cxform"); if (cXform.hasAddTerms()) { Element add = element.addElement("add"); add.addAttribute("r", Integer.toString(cXform.getRedAddTerm())); add.addAttribute("g", Integer.toString(cXform.getGreenAddTerm())); add.addAttribute("b", Integer.toString(cXform.getBlueAddTerm())); } if (cXform.hasMultTerms()) { Element mult = element.addElement("mult"); mult.addAttribute("r", Integer.toString(cXform.getRedMultTerm())); mult.addAttribute("g", Integer.toString(cXform.getGreenMultTerm())); mult.addAttribute("b", Integer.toString(cXform.getBlueMultTerm())); } } static void writeCXFormWithAlpha( Element parentElement, CXformWithAlpha cXformWithAlpha) { Element element = parentElement.addElement("cxformwithalpha"); if (cXformWithAlpha.hasAddTerms()) { Element add = element.addElement("add"); add.addAttribute("r", Integer.toString(cXformWithAlpha.getRedAddTerm())); add.addAttribute( "g", Integer.toString(cXformWithAlpha.getGreenAddTerm())); add.addAttribute("b", Integer.toString(cXformWithAlpha.getBlueAddTerm())); add.addAttribute( "a", Integer.toString(cXformWithAlpha.getAlphaAddTerm())); } if (cXformWithAlpha.hasMultTerms()) { Element mult = element.addElement("mult"); mult.addAttribute( "r", Integer.toString(cXformWithAlpha.getRedMultTerm())); mult.addAttribute( "g", Integer.toString(cXformWithAlpha.getGreenMultTerm())); mult.addAttribute( "b", Integer.toString(cXformWithAlpha.getBlueMultTerm())); mult.addAttribute( "a", Integer.toString(cXformWithAlpha.getAlphaMultTerm())); } } static void writeClipActions(Element parentElement, ClipActions clipActions) { Element element = parentElement.addElement("clipactions"); writeClipEventFlags(element, clipActions.getEventFlags()); List records = clipActions.getClipActionRecords(); for (Iterator it = records.iterator(); it.hasNext();) { ClipActionRecord record = (ClipActionRecord) it.next(); Element recordElement = element.addElement("clipactionrecord"); ClipEventFlags eventFlags = record.getEventFlags(); writeClipEventFlags(recordElement, eventFlags); if (eventFlags.isKeyPress()) { recordElement.addAttribute( "keycode", Short.toString(record.getKeyCode())); } writeActionBlock(recordElement, record.getActions()); } } static void writeColor( Element parentElement, String elementName, Color color) { if (color instanceof RGB) { writeRGB(parentElement, elementName, (RGB) color); } else { writeRGBA(parentElement, elementName, (RGBA) color); } } static void writeFilters(Element parentElement, List filters) { Element element = parentElement.addElement("filters"); for (int j = 0; j < filters.size(); j++) { Object filter = filters.get(j); if (filter instanceof ColorMatrixFilter) { ColorMatrixFilter colorMatrixFilter = (ColorMatrixFilter) filter; Element filterElement = element.addElement("colormatrix"); float[] matrix = colorMatrixFilter.getMatrix(); for (int i = 0; i < matrix.length; i++) { filterElement.addElement("val").addText( StringUtilities.doubleToString(matrix[i])); } } else if (filter instanceof ConvolutionFilter) { ConvolutionFilter convolutionFilter = (ConvolutionFilter) filter; Element filterElement = element.addElement("convolution"); Element matrixElement = filterElement.addElement( "matrix"); matrixElement.addAttribute( "rows", Integer.toString(convolutionFilter.getMatrixRows())); float[] matrix = convolutionFilter.getMatrix(); for (int i = 0; i < matrix.length; i++) { matrixElement.addElement("val").addText( StringUtilities.doubleToString(matrix[i])); } writeRGBA(filterElement, "color", convolutionFilter.getColor()); filterElement.addAttribute( "divisor", StringUtilities.doubleToString(convolutionFilter.getDivisor())); filterElement.addAttribute( "bias", StringUtilities.doubleToString(convolutionFilter.getBias())); if (convolutionFilter.isClamp()) { filterElement.addAttribute("clamp", "true"); } if (convolutionFilter.isPreserveAlpha()) { filterElement.addAttribute("preservealpha", "true"); } } else if (filter instanceof BlurFilter) { BlurFilter blurFilter = (BlurFilter) filter; Element filterElement = element.addElement("blur"); filterElement.addAttribute( "x", StringUtilities.doubleToString(blurFilter.getX())); filterElement.addAttribute( "y", StringUtilities.doubleToString(blurFilter.getY())); filterElement.addAttribute( "quality", Integer.toString(blurFilter.getQuality())); } else if (filter instanceof DropShadowFilter) { DropShadowFilter dropShadowFilter = (DropShadowFilter) filter; Element filterElement = element.addElement("dropshadow"); writeRGBA(filterElement, "color", dropShadowFilter.getColor()); filterElement.addAttribute( "x", StringUtilities.doubleToString(dropShadowFilter.getX())); filterElement.addAttribute( "y", StringUtilities.doubleToString(dropShadowFilter.getY())); filterElement.addAttribute( "angle", StringUtilities.doubleToString(dropShadowFilter.getAngle())); filterElement.addAttribute( "distance", StringUtilities.doubleToString(dropShadowFilter.getDistance())); filterElement.addAttribute( "strength", StringUtilities.doubleToString(dropShadowFilter.getStrength())); filterElement.addAttribute( "quality", Integer.toString(dropShadowFilter.getQuality())); if (dropShadowFilter.isInner()) { filterElement.addAttribute("inner", "true"); } if (dropShadowFilter.isKnockout()) { filterElement.addAttribute("knockout", "true"); } if (dropShadowFilter.isHideObject()) { filterElement.addAttribute("hideobject", "true"); } } else if (filter instanceof GlowFilter) { GlowFilter glowFilter = (GlowFilter) filter; Element filterElement = element.addElement("glow"); writeRGBA(filterElement, "color", glowFilter.getColor()); filterElement.addAttribute( "x", StringUtilities.doubleToString(glowFilter.getX())); filterElement.addAttribute( "y", StringUtilities.doubleToString(glowFilter.getY())); filterElement.addAttribute( "strength", StringUtilities.doubleToString(glowFilter.getStrength())); filterElement.addAttribute( "quality", Integer.toString(glowFilter.getQuality())); if (glowFilter.isInner()) { filterElement.addAttribute("inner", "true"); } if (glowFilter.isKnockout()) { filterElement.addAttribute("knockout", "true"); } } else if (filter instanceof BevelFilter) { BevelFilter bevelFilter = (BevelFilter) filter; Element filterElement = element.addElement("bevel"); writeRGBA( filterElement, "highlightcolor", bevelFilter.getHighlightColor()); writeRGBA(filterElement, "shadowcolor", bevelFilter.getShadowColor()); filterElement.addAttribute( "x", StringUtilities.doubleToString(bevelFilter.getX())); filterElement.addAttribute( "y", StringUtilities.doubleToString(bevelFilter.getY())); filterElement.addAttribute( "angle", StringUtilities.doubleToString(bevelFilter.getAngle())); filterElement.addAttribute( "distance", StringUtilities.doubleToString(bevelFilter.getDistance())); filterElement.addAttribute( "strength", StringUtilities.doubleToString(bevelFilter.getStrength())); filterElement.addAttribute( "quality", Integer.toString(bevelFilter.getQuality())); if (bevelFilter.isInner()) { filterElement.addAttribute("inner", "true"); } if (bevelFilter.isKnockout()) { filterElement.addAttribute("knockout", "true"); } if (bevelFilter.isOnTop()) { filterElement.addAttribute("ontop", "true"); } } else if (filter instanceof GradientGlowFilter) { GradientGlowFilter gradientGlowFilter = (GradientGlowFilter) filter; Element filterElement = element.addElement( "gradientglow"); RGBA[] colors = gradientGlowFilter.getColors(); short[] ratios = gradientGlowFilter.getRatios(); int controlPointsCount = colors.length; Element pointsElement = filterElement.addElement( "controlpoints"); for (int i = 0; i < controlPointsCount; i++) { Element pointElement = pointsElement.addElement("controlpoint"); pointElement.addAttribute("ratio", Short.toString(ratios[i])); writeRGBA(pointElement, "color", colors[i]); } filterElement.addAttribute( "x", StringUtilities.doubleToString(gradientGlowFilter.getX())); filterElement.addAttribute( "y", StringUtilities.doubleToString(gradientGlowFilter.getY())); filterElement.addAttribute( "angle", StringUtilities.doubleToString( gradientGlowFilter.getAngle())); filterElement.addAttribute( "distance", StringUtilities.doubleToString(gradientGlowFilter.getDistance())); filterElement.addAttribute( "strength", StringUtilities.doubleToString(gradientGlowFilter.getStrength())); filterElement.addAttribute( "quality", Integer.toString(gradientGlowFilter.getQuality())); if (gradientGlowFilter.isInner()) { filterElement.addAttribute("inner", "true"); } if (gradientGlowFilter.isKnockout()) { filterElement.addAttribute("knockout", "true"); } if (gradientGlowFilter.isOnTop()) { filterElement.addAttribute("ontop", "true"); } } else if (filter instanceof GradientBevelFilter) { GradientBevelFilter gradientBevelFilter = (GradientBevelFilter) filter; Element filterElement = element.addElement( "gradientbevel"); RGBA[] colors = gradientBevelFilter.getColors(); short[] ratios = gradientBevelFilter.getRatios(); int controlPointsCount = colors.length; Element pointsElement = filterElement.addElement( "controlpoints"); for (int i = 0; i < controlPointsCount; i++) { Element pointElement = pointsElement.addElement("controlpoint"); pointElement.addAttribute("ratio", Short.toString(ratios[i])); writeRGBA(pointElement, "color", colors[i]); } filterElement.addAttribute( "x", StringUtilities.doubleToString(gradientBevelFilter.getX())); filterElement.addAttribute( "y", StringUtilities.doubleToString(gradientBevelFilter.getY())); filterElement.addAttribute( "angle", StringUtilities.doubleToString(gradientBevelFilter.getAngle())); filterElement.addAttribute( "distance", StringUtilities.doubleToString(gradientBevelFilter.getDistance())); filterElement.addAttribute( "strength", StringUtilities.doubleToString(gradientBevelFilter.getStrength())); filterElement.addAttribute( "quality", Integer.toString(gradientBevelFilter.getQuality())); if (gradientBevelFilter.isInner()) { filterElement.addAttribute("inner", "true"); } if (gradientBevelFilter.isKnockout()) { filterElement.addAttribute("knockout", "true"); } if (gradientBevelFilter.isOnTop()) { filterElement.addAttribute("ontop", "true"); } } } } static void writeMatrix(Element parentElement, Matrix matrix) { writeMatrix(parentElement, "matrix", matrix); } static void writeMatrix( Element parentElement, String elementName, Matrix matrix) { Element element = parentElement.addElement(elementName); Element translate = element.addElement("translate"); translate.addAttribute("x", Integer.toString(matrix.getTranslateX())); translate.addAttribute("y", Integer.toString(matrix.getTranslateY())); if (matrix.hasRotateSkew()) { Element rotateSkew = element.addElement("rotateskew"); rotateSkew.addAttribute( "rs0", StringUtilities.doubleToString(matrix.getRotateSkew0())); rotateSkew.addAttribute( "rs1", StringUtilities.doubleToString(matrix.getRotateSkew1())); } if (matrix.hasScale()) { Element scale = element.addElement("scale"); scale.addAttribute( "x", StringUtilities.doubleToString(matrix.getScaleX())); scale.addAttribute( "y", StringUtilities.doubleToString(matrix.getScaleY())); } } static void writeMorphFillStyles( Element parentElement, MorphFillStyles fillStyles) { int size = fillStyles.getSize(); Element fillStylesElement = parentElement.addElement("morphfillstyles"); for (int i = 1; i <= size; i++) { MorphFillStyle fillStyle = fillStyles.getStyle(i); writeMorphFillStyle(fillStylesElement, fillStyle); } } static void writeMorphLineStyles( Element parentElement, MorphLineStyles lineStyles) { int size = lineStyles.getSize(); Element lineStylesElement = parentElement.addElement("morphlinestyles"); for (int i = 1; i <= size; i++) { Object style = lineStyles.getStyle(i); if (style instanceof MorphLineStyle) { MorphLineStyle lineStyle = (MorphLineStyle) style; Element lineStyleElement = lineStylesElement.addElement( "morphlinestyle"); Element startElement = lineStyleElement.addElement("start"); startElement.addAttribute( "width", Integer.toString(lineStyle.getStartWidth())); writeRGBA(startElement, "color", lineStyle.getStartColor()); Element endElement = lineStyleElement.addElement("end"); endElement.addAttribute( "width", Integer.toString(lineStyle.getEndWidth())); writeRGBA(endElement, "color", lineStyle.getEndColor()); } else { MorphLineStyle2 lineStyle2 = (MorphLineStyle2) style; Element lineStyle2Element = lineStylesElement.addElement( "morphlinestyle2"); Element startElement = lineStyle2Element.addElement("start"); Element end = lineStyle2Element.addElement("end"); startElement.addAttribute( "width", Integer.toString(lineStyle2.getStartWidth())); end.addAttribute("width", Integer.toString(lineStyle2.getEndWidth())); writeEnhancedStrokeStyles( lineStyle2Element, lineStyle2.getJointStyle(), lineStyle2.getStartCapStyle(), lineStyle2.getEndCapStyle(), lineStyle2.getMiterLimit(), lineStyle2.getScaleStroke()); if (lineStyle2.isClose()) { parentElement.addAttribute("close", "true"); } if (lineStyle2.isPixelHinting()) { parentElement.addAttribute("pixelhinting", "true"); } MorphFillStyle fillStyle = lineStyle2.getFillStyle(); if (fillStyle == null) { writeColor(startElement, "color", lineStyle2.getStartColor()); writeColor(end, "color", lineStyle2.getEndColor()); } else { writeMorphFillStyle(lineStyle2Element, fillStyle); } } } } static void writeRGB(Element parentElement, String elementName, RGB rgbColor) { Element element = parentElement.addElement(elementName); element.addAttribute("r", Integer.toString(rgbColor.getRed())); element.addAttribute("g", Integer.toString(rgbColor.getGreen())); element.addAttribute("b", Integer.toString(rgbColor.getBlue())); } static void writeRGBA( Element parentElement, String elementName, RGBA rgbaColor) { Element element = parentElement.addElement(elementName); element.addAttribute("r", Integer.toString(rgbaColor.getRed())); element.addAttribute("g", Integer.toString(rgbaColor.getGreen())); element.addAttribute("b", Integer.toString(rgbaColor.getBlue())); element.addAttribute("a", Integer.toString(rgbaColor.getAlpha())); } static void writeRect(Element parentElement, String elementName, Rect rect) { Element element = parentElement.addElement(elementName); element.addAttribute("xmin", Long.toString(rect.getXMin())); element.addAttribute("xmax", Long.toString(rect.getXMax())); element.addAttribute("ymin", Long.toString(rect.getYMin())); element.addAttribute("ymax", Long.toString(rect.getYMax())); } static void writeShape(Element parentElement, Shape shape) { Element element = parentElement.addElement("shape"); ShapeRecord[] records = shape.getShapeRecords(); for (int i = 0; i < records.length; i++) { writeShapeRecord(element, records[i]); } } static void writeShapeRecord(Element parentElement, ShapeRecord shapeRecord) { if (shapeRecord instanceof CurvedEdgeRecord) { writeCurvedEdgeRecord(parentElement, (CurvedEdgeRecord) shapeRecord); } else if (shapeRecord instanceof StraightEdgeRecord) { writeStraightEdgeRecord(parentElement, (StraightEdgeRecord) shapeRecord); } else { writeStyleChangeRecord(parentElement, (StyleChangeRecord) shapeRecord); } } static void writeShapeWithStyle( Element parentElement, ShapeWithStyle shapeWithStyle) { Element element = parentElement.addElement("shapewithstyle"); Element shapeElement = element.addElement("shape"); ShapeRecord[] records = shapeWithStyle.getShapeRecords(); for (int i = 0; i < records.length; i++) { writeShapeRecord(shapeElement, records[i]); } writeLineStyles(element, shapeWithStyle.getLineStyles()); writeFillStyles(element, shapeWithStyle.getFillStyles()); } static void writeSoundInfo(Element parentElement, SoundInfo soundInfo) { Element element = parentElement.addElement("soundinfo"); if (soundInfo.isSyncStop()) { element.addAttribute("syncstop", "true"); } if (soundInfo.isSyncNoMultiple()) { element.addAttribute("syncnomultiple", "true"); } if (soundInfo.hasLoops()) { element.addAttribute( "loopcount", Integer.toString(soundInfo.getLoopCount())); } if (soundInfo.hasInPoint()) { element.addAttribute("inpoint", Long.toString(soundInfo.getInPoint())); } if (soundInfo.hasOutPoint()) { element.addAttribute("outpoint", Long.toString(soundInfo.getOutPoint())); } if (soundInfo.hasEnvelope()) { Element recordsElement = element.addElement("enveloperecords"); SoundEnvelope[] records = soundInfo.getEnvelopeRecords(); for (int i = 0; i < records.length; i++) { RecordXMLWriter.writeSoundEnvelope(recordsElement, records[i]); } } } static void writeTextRecord(Element parentElement, TextRecord record) { Element element = parentElement.addElement("textrecord"); if (record.hasFont()) { element.addAttribute("fontid", Integer.toString(record.getFontId())); element.addAttribute("height", Integer.toString(record.getTextHeight())); } if (record.hasXOffset()) { element.addAttribute("xoffset", Short.toString(record.getXOffset())); } if (record.hasYOffset()) { element.addAttribute("yoffset", Short.toString(record.getYOffset())); } if (record.hasColor()) { writeColor(element, "color", record.getTextColor()); } GlyphEntry[] glyphEntries = record.getGlyphEntries(); Element glyphEntriesElement = element.addElement("glyphentries"); for (int i = 0; i < glyphEntries.length; i++) { GlyphEntry glyphEntry = glyphEntries[i]; Element glyphEntryElement = glyphEntriesElement.addElement("glyphentry"); glyphEntryElement.addAttribute( "index", Integer.toString(glyphEntry.getGlyphIndex())); glyphEntryElement.addAttribute( "advance", Integer.toString(glyphEntry.getGlyphAdvance())); } } static void writeZlibBitmapData(Element parentElement, ZlibBitmapData data) { if (data instanceof BitmapData) { writeBitmapData(parentElement, (BitmapData) data); } else if (data instanceof ColorMapData) { writeColorMapData(parentElement, (ColorMapData) data); } else if (data instanceof AlphaBitmapData) { writeAlphaBitmapData(parentElement, (AlphaBitmapData) data); } else { writeAlphaColorMapData(parentElement, (AlphaColorMapData) data); } } private static void writeAlphaBitmapData( Element parentElement, AlphaBitmapData data) { Element element = parentElement.addElement("alphabitmapdata"); RGBA[] pixelData = data.getBitmapPixelData(); writeRGBAArray(element, pixelData); } private static void writeAlphaColorMapData( Element parentElement, AlphaColorMapData data) { Element element = parentElement.addElement("alphacolormapdata"); Element colorTableElement = element.addElement("colortable"); RGBA[] colorTable = data.getColorTableRGBA(); writeRGBAArray(colorTableElement, colorTable); Element pixelDataElement = element.addElement("pixeldata"); short[] pixelData = data.getColorMapPixelData(); pixelDataElement.addText(Base64.encodeUnsigned(pixelData)); } private static void writeBitmapData(Element parentElement, BitmapData data) { Element element = parentElement.addElement("bitmapdata"); BitmapPixelData[] pixelData = data.getBitmapPixelData(); if (pixelData[0] instanceof Pix15) { // array is homogeneous writePix15Array(element, (Pix15[]) pixelData); } else { writePix24Array(element, (Pix24[]) pixelData); } } private static void writeClipEventFlags( Element parentElement, ClipEventFlags flags) { Element element = parentElement.addElement("clipeventflags"); if (flags.isKeyUp()) { element.addAttribute("keyup", "true"); } if (flags.isKeyDown()) { element.addAttribute("keydown", "true"); } if (flags.isKeyPress()) { element.addAttribute("keypress", "true"); } if (flags.isMouseUp()) { element.addAttribute("mouseup", "true"); } if (flags.isMouseDown()) { element.addAttribute("mousedown", "true"); } if (flags.isMouseMove()) { element.addAttribute("mousemove", "true"); } if (flags.isLoad()) { element.addAttribute("load", "true"); } if (flags.isUnload()) { element.addAttribute("unload", "true"); } if (flags.isEnterFrame()) { element.addAttribute("enterframe", "true"); } if (flags.isDragOver()) { element.addAttribute("dragover", "true"); } if (flags.isDragOut()) { element.addAttribute("dragout", "true"); } if (flags.isRollOver()) { element.addAttribute("rollover", "true"); } if (flags.isRollOut()) { element.addAttribute("rollout", "true"); } if (flags.isReleaseOutside()) { element.addAttribute("releaseoutside", "true"); } if (flags.isRelease()) { element.addAttribute("release", "true"); } if (flags.isPress()) { element.addAttribute("press", "true"); } if (flags.isInitialize()) { element.addAttribute("initialize", "true"); } if (flags.isData()) { element.addAttribute("data", "true"); } if (flags.isConstruct()) { element.addAttribute("construct", "true"); } } private static void writeColorMapData( Element parentElement, ColorMapData data) { Element element = parentElement.addElement("colormapdata"); Element colorTableElement = element.addElement("colortable"); RGB[] colorTable = data.getColorTableRGB(); writeRGBArray(colorTableElement, colorTable); Element pixelDataElement = element.addElement("pixeldata"); short[] pixelData = data.getColorMapPixelData(); pixelDataElement.addText(Base64.encodeUnsigned(pixelData)); } private static void writeCurvedEdgeRecord( Element parentElement, CurvedEdgeRecord curvedEdgeRecord) { Element element = parentElement.addElement("curvededgerecord"); element.addAttribute( "anchordx", Integer.toString(curvedEdgeRecord.getAnchorDeltaX())); element.addAttribute( "anchordy", Integer.toString(curvedEdgeRecord.getAnchorDeltaY())); element.addAttribute( "controldx", Integer.toString(curvedEdgeRecord.getControlDeltaX())); element.addAttribute( "controldy", Integer.toString(curvedEdgeRecord.getControlDeltaY())); } private static void writeEnhancedStrokeStyles( Element parentElement, byte jointStyle, byte startCapStyle, byte endCapStyle, double miterLimit, byte scaleStroke) { switch (jointStyle) { case EnhancedStrokeStyle.JOINT_ROUND: parentElement.addAttribute("joint", "round"); break; case EnhancedStrokeStyle.JOINT_MITER: parentElement.addAttribute("joint", "miter"); parentElement.addAttribute( "miterlimit", StringUtilities.doubleToString(miterLimit)); break; case EnhancedStrokeStyle.JOINT_BEVEL: parentElement.addAttribute("joint", "bevel"); break; } Element capStyleElement = parentElement.addElement("capstyle"); switch (startCapStyle) { case EnhancedStrokeStyle.CAPS_NONE: capStyleElement.addAttribute("start", "none"); break; case EnhancedStrokeStyle.CAPS_ROUND: capStyleElement.addAttribute("start", "round"); break; case EnhancedStrokeStyle.CAPS_SQUARE: capStyleElement.addAttribute("start", "square"); break; } switch (endCapStyle) { case EnhancedStrokeStyle.CAPS_NONE: capStyleElement.addAttribute("end", "none"); break; case EnhancedStrokeStyle.CAPS_ROUND: capStyleElement.addAttribute("end", "round"); break; case EnhancedStrokeStyle.CAPS_SQUARE: capStyleElement.addAttribute("end", "square"); break; } switch (scaleStroke) { case EnhancedStrokeStyle.SCALE_NONE: parentElement.addAttribute("scalestroke", "none"); break; case EnhancedStrokeStyle.SCALE_HORIZONTAL: parentElement.addAttribute("scalestroke", "horizontal"); break; case EnhancedStrokeStyle.SCALE_VERTICAL: parentElement.addAttribute("scalestroke", "vertical"); break; case EnhancedStrokeStyle.SCALE_BOTH: parentElement.addAttribute("scalestroke", "both"); break; } } private static void writeFillStyle( Element parentElement, FillStyle fillStyle) { Element fillStyleElement = parentElement.addElement("fillstyle"); boolean isGradient = false; boolean isFocal = false; boolean isBitmap = false; switch (fillStyle.getType()) { case FillStyle.TYPE_SOLID: fillStyleElement.addAttribute("type", "solid"); writeColor(fillStyleElement, "color", fillStyle.getColor()); break; case FillStyle.TYPE_LINEAR_GRADIENT: fillStyleElement.addAttribute("type", "lineargradient"); isGradient = true; break; case FillStyle.TYPE_FOCAL_RADIAL_GRADIENT: fillStyleElement.addAttribute("type", "focalradialgradient"); isGradient = true; isFocal = true; break; case FillStyle.TYPE_RADIAL_GRADIENT: fillStyleElement.addAttribute("type", "radialgradient"); isGradient = true; break; case FillStyle.TYPE_TILED_BITMAP: fillStyleElement.addAttribute("type", "tiledbitmap"); isBitmap = true; break; case FillStyle.TYPE_CLIPPED_BITMAP: fillStyleElement.addAttribute("type", "clippedbitmap"); isBitmap = true; break; case FillStyle.TYPE_NONSMOOTHED_TILED_BITMAP: fillStyleElement.addAttribute("type", "nonsmoothedtiledbitmap"); isBitmap = true; break; case FillStyle.TYPE_NONSMOOTHED_CLIPPED_BITMAP: fillStyleElement.addAttribute("type", "nonsmoothedclippedbitmap"); isBitmap = true; break; default: throw new IllegalArgumentException( "Illegal fill type: " + fillStyle.getType()); } if (isGradient) { if (isFocal) { writeFocalGradient( fillStyleElement.addElement("focalgradient"), (FocalGradient) fillStyle.getGradient()); } else { writeGradient( fillStyleElement.addElement("gradient"), fillStyle.getGradient()); } writeMatrix( fillStyleElement, "gradientmatrix", fillStyle.getGradientMatrix()); } else if (isBitmap) { fillStyleElement.addAttribute( "bitmapid", Integer.toString(fillStyle.getBitmapId())); writeMatrix( fillStyleElement, "bitmapmatrix", fillStyle.getBitmapMatrix()); } } private static void writeFillStyles( Element parentElement, FillStyleArray fillStyles) { int size = fillStyles.getSize(); Element fillStylesElement = parentElement.addElement("fillstyles"); for (int i = 1; i <= size; i++) { FillStyle fillStyle = fillStyles.getStyle(i); writeFillStyle(fillStylesElement, fillStyle); } } private static void writeFocalGradient( Element gradientElement, FocalGradient gradient) { writeGradient(gradientElement, gradient); gradientElement.addAttribute( "focalpointratio", StringUtilities.doubleToString(gradient.getFocalPointRatio())); } private static void writeFocalMorphGradient( Element gradientElement, FocalMorphGradient gradient) { writeMorphGradient(gradientElement, gradient); gradientElement.addAttribute( "startfocalpointratio", StringUtilities.doubleToString(gradient.getStartFocalPointRatio())); gradientElement.addAttribute( "endfocalpointratio", StringUtilities.doubleToString(gradient.getEndFocalPointRatio())); } private static void writeGradient(Element gradientElement, Gradient gradient) { switch (gradient.getInterpolationMethod()) { case Gradient.INTERPOLATION_LINEAR_RGB: gradientElement.addAttribute("interpolation", "linear-rgb"); break; case Gradient.INTERPOLATION_RGB: gradientElement.addAttribute("interpolation", "rgb"); break; } switch (gradient.getSpreadMethod()) { case Gradient.SPREAD_PAD: gradientElement.addAttribute("spread", "pad"); break; case Gradient.SPREAD_REFLECT: gradientElement.addAttribute("spread", "reflect"); break; case Gradient.SPREAD_REPEAT: gradientElement.addAttribute("spread", "repeat"); break; } GradRecord[] records = gradient.getGradientRecords(); for (int i = 0; i < records.length; i++) { GradRecord record = records[i]; Element recordElement = gradientElement.addElement("gradrecord"); recordElement.addAttribute("ratio", Short.toString(record.getRatio())); writeColor(recordElement, "color", record.getColor()); } } private static void writeLineStyles( Element parentElement, LineStyleArray lineStyles) { int size = lineStyles.getSize(); Element lineStylesElement = parentElement.addElement("linestyles"); for (int i = 1; i <= size; i++) { Object style = lineStyles.getStyle(i); if (style instanceof LineStyle) { LineStyle lineStyle = (LineStyle) style; Element lineStyleElement = lineStylesElement.addElement("linestyle"); lineStyleElement.addAttribute( "width", Integer.toString(lineStyle.getWidth())); writeColor(lineStyleElement, "color", lineStyle.getColor()); } else { LineStyle2 lineStyle2 = (LineStyle2) style; Element lineStyle2Element = lineStylesElement.addElement("linestyle2"); lineStyle2Element.addAttribute( "width", Integer.toString(lineStyle2.getWidth())); writeEnhancedStrokeStyles( lineStyle2Element, lineStyle2.getJointStyle(), lineStyle2.getStartCapStyle(), lineStyle2.getEndCapStyle(), lineStyle2.getMiterLimit(), lineStyle2.getScaleStroke()); if (lineStyle2.isClose()) { parentElement.addAttribute("close", "true"); } if (lineStyle2.isPixelHinting()) { parentElement.addAttribute("pixelhinting", "true"); } FillStyle fillStyle = lineStyle2.getFillStyle(); if (fillStyle == null) { writeColor(lineStyle2Element, "color", lineStyle2.getColor()); } else { writeFillStyle(lineStyle2Element, fillStyle); } } } } private static void writeMorphFillStyle( Element parentElement, MorphFillStyle fillStyle) { Element fillStyleElement = parentElement.addElement("morphfillstyle"); Element start = fillStyleElement.addElement("start"); Element end = fillStyleElement.addElement("end"); boolean isGradient = false; boolean isFocal = false; boolean isBitmap = false; switch (fillStyle.getType()) { case FillStyle.TYPE_SOLID: fillStyleElement.addAttribute("type", "solid"); writeRGBA(start, "color", fillStyle.getStartColor()); writeRGBA(end, "color", fillStyle.getEndColor()); break; case FillStyle.TYPE_LINEAR_GRADIENT: fillStyleElement.addAttribute("type", "lineargradient"); isGradient = true; break; case FillStyle.TYPE_FOCAL_RADIAL_GRADIENT: fillStyleElement.addAttribute("type", "focalradialgradient"); isGradient = true; isFocal = true; break; case FillStyle.TYPE_RADIAL_GRADIENT: fillStyleElement.addAttribute("type", "radialgradient"); isGradient = true; break; case FillStyle.TYPE_TILED_BITMAP: fillStyleElement.addAttribute("type", "tiledbitmap"); isBitmap = true; break; case FillStyle.TYPE_CLIPPED_BITMAP: fillStyleElement.addAttribute("type", "clippedbitmap"); isBitmap = true; break; case FillStyle.TYPE_NONSMOOTHED_TILED_BITMAP: fillStyleElement.addAttribute("type", "nonsmoothedtiledbitmap"); isBitmap = true; break; case FillStyle.TYPE_NONSMOOTHED_CLIPPED_BITMAP: fillStyleElement.addAttribute("type", "nonsmoothedclippedbitmap"); isBitmap = true; break; default: throw new IllegalArgumentException( "Illegal morph fill type: " + fillStyle.getType()); } if (isGradient) { if (isFocal) { writeFocalMorphGradient( fillStyleElement.addElement("focalmorphgradient"), (FocalMorphGradient) fillStyle.getGradient()); } else { writeMorphGradient( fillStyleElement.addElement("morphgradient"), fillStyle.getGradient()); } writeMatrix(start, "gradientmatrix", fillStyle.getStartGradientMatrix()); writeMatrix(end, "gradientmatrix", fillStyle.getEndGradientMatrix()); } else if (isBitmap) { fillStyleElement.addAttribute( "bitmapid", Integer.toString(fillStyle.getBitmapId())); writeMatrix(start, "bitmapmatrix", fillStyle.getStartBitmapMatrix()); writeMatrix(end, "bitmapmatrix", fillStyle.getEndBitmapMatrix()); } } private static void writeMorphGradient( Element gradientElement, MorphGradient gradient) { switch (gradient.getInterpolationMethod()) { case Gradient.INTERPOLATION_LINEAR_RGB: gradientElement.addAttribute("interpolation", "linear-rgb"); break; case Gradient.INTERPOLATION_RGB: gradientElement.addAttribute("interpolation", "rgb"); break; } switch (gradient.getSpreadMethod()) { case Gradient.SPREAD_PAD: gradientElement.addAttribute("spread", "pad"); break; case Gradient.SPREAD_REFLECT: gradientElement.addAttribute("spread", "reflect"); break; case Gradient.SPREAD_REPEAT: gradientElement.addAttribute("spread", "repeat"); break; } MorphGradRecord[] records = gradient.getGradientRecords(); for (int i = 0; i < records.length; i++) { MorphGradRecord record = records[i]; Element recordElement = gradientElement.addElement("morphgradrecord"); Element start = recordElement.addElement("start"); start.addAttribute("ratio", Short.toString(record.getStartRatio())); writeRGBA(start, "color", record.getStartColor()); Element end = recordElement.addElement("end"); end.addAttribute("ratio", Short.toString(record.getEndRatio())); writeRGBA(end, "color", record.getEndColor()); } } private static void writePix15Array(Element parentElement, Pix15[] data) { Element element = parentElement.addElement("pix15array"); byte[] buffer = new byte[data.length * 3]; for (int i = 0; i < data.length; i++) { Pix15 pix15 = data[i]; buffer[i * 3] = pix15.getRed(); buffer[(i * 3) + 1] = pix15.getGreen(); buffer[(i * 3) + 2] = pix15.getBlue(); } element.addText(Base64.encode(buffer)); } private static void writePix24Array(Element parentElement, Pix24[] data) { Element element = parentElement.addElement("pix24array"); short[] buffer = new short[data.length * 3]; for (int i = 0; i < data.length; i++) { Pix24 pix24 = data[i]; buffer[i * 3] = pix24.getRed(); buffer[(i * 3) + 1] = pix24.getGreen(); buffer[(i * 3) + 2] = pix24.getBlue(); } element.addText(Base64.encodeUnsigned(buffer)); } private static void writeRGBAArray(Element parentElement, RGBA[] data) { Element element = parentElement.addElement("rgbaarray"); short[] buffer = new short[data.length * 4]; for (int i = 0; i < data.length; i++) { RGBA rgba = data[i]; buffer[i * 4] = rgba.getRed(); buffer[(i * 4) + 1] = rgba.getGreen(); buffer[(i * 4) + 2] = rgba.getBlue(); buffer[(i * 4) + 3] = rgba.getAlpha(); } element.addText(Base64.encodeUnsigned(buffer)); } private static void writeRGBArray(Element parentElement, RGB[] data) { Element element = parentElement.addElement("rgbarray"); short[] buffer = new short[data.length * 3]; for (int i = 0; i < data.length; i++) { RGB rgb = data[i]; buffer[i * 3] = rgb.getRed(); buffer[(i * 3) + 1] = rgb.getGreen(); buffer[(i * 3) + 2] = rgb.getBlue(); } element.addText(Base64.encodeUnsigned(buffer)); } private static void writeSoundEnvelope( Element parentElement, SoundEnvelope soundEnvelope) { Element element = parentElement.addElement("soundenvelope"); element.addAttribute("pos44", Long.toString(soundEnvelope.getPos44())); element.addAttribute( "leftlevel", Integer.toString(soundEnvelope.getLeftLevel())); element.addAttribute( "rightlevel", Integer.toString(soundEnvelope.getRightLevel())); } private static void writeStraightEdgeRecord( Element parentElement, StraightEdgeRecord straightEdgeRecord) { Element element = parentElement.addElement("straightedgerecord"); element.addAttribute( "dx", Integer.toString(straightEdgeRecord.getDeltaX())); element.addAttribute( "dy", Integer.toString(straightEdgeRecord.getDeltaY())); } private static void writeStyleChangeRecord( Element parentElement, StyleChangeRecord styleChangeRecord) { Element element = parentElement.addElement("stylechangerecord"); if (styleChangeRecord.hasMoveTo()) { Element moveTo = element.addElement("moveto"); moveTo.addAttribute( "x", Integer.toString(styleChangeRecord.getMoveToX())); moveTo.addAttribute( "y", Integer.toString(styleChangeRecord.getMoveToY())); } if ( styleChangeRecord.hasLineStyle() || styleChangeRecord.hasFillStyle0() || styleChangeRecord.hasFillStyle1() || styleChangeRecord.hasNewStyles()) { Element styles = element.addElement("styles"); if (styleChangeRecord.hasLineStyle()) { styles.addAttribute( "line", Integer.toString(styleChangeRecord.getLineStyle())); } if (styleChangeRecord.hasFillStyle0()) { styles.addAttribute( "fill0", Integer.toString(styleChangeRecord.getFillStyle0())); } if (styleChangeRecord.hasFillStyle1()) { styles.addAttribute( "fill1", Integer.toString(styleChangeRecord.getFillStyle1())); } if (styleChangeRecord.hasNewStyles()) { writeLineStyles(styles, styleChangeRecord.getNewLineStyles()); writeFillStyles(styles, styleChangeRecord.getNewFillStyles()); } } } }