/* * 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.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 org.dom4j.Attribute; import org.dom4j.Element; import java.util.ArrayList; import java.util.Iterator; import java.util.List; class RecordXMLReader { static boolean getBooleanAttribute(String name, Element parentElement) { // boolean attributes are written only for "true" values Attribute attribute = parentElement.attribute(name); return ((attribute != null) && attribute.getValue().equalsIgnoreCase("true")); } static int getCharacterId(Element parentElement) { return getIntAttribute("charid", parentElement); } static byte[] getDataElement(String elementName, Element parentElement) { Element element = parentElement.element(elementName); if (element == null) { throw new MissingElementException(elementName, parentElement.getPath()); } return Base64.decode(element.getText()); } static double getDoubleAttribute(String attributeName, Element parentElement) { return Double.parseDouble(getStringAttribute(attributeName, parentElement)); } static Element getElement(String elementName, Element parentElement) { Element result = parentElement.element(elementName); if (result == null) { throw new MissingElementException(elementName, parentElement.getPath()); } return result; } static float getFloatAttribute(String attributeName, Element parentElement) { return Float.parseFloat(getStringAttribute(attributeName, parentElement)); } static int getIntAttribute(String attributeName, Element parentElement) { return Integer.parseInt(getStringAttribute(attributeName, parentElement)); } static long getLongAttribute(String attributeName, Element parentElement) { return Long.parseLong(getStringAttribute(attributeName, parentElement)); } static short getShortAttribute(String attributeName, Element parentElement) { return Short.parseShort(getStringAttribute(attributeName, parentElement)); } static String getStringAttribute(String attributeName, Element parentElement) { Attribute attribute = parentElement.attribute(attributeName); if (attribute == null) { throw new MissingAttributeException( attributeName, parentElement.getPath()); } return attribute.getValue(); } static void readActionBlock(ActionBlockReader actionBlock, Element parentElement) { Element blockElement = getElement("actionblock", parentElement); List actionElements = blockElement.elements(); for (Iterator it = actionElements.iterator(); it.hasNext();) { Element actionElement = (Element) it.next(); Action action = ActionXMLReader.readAction(actionElement); actionBlock.addAction(action); } } static AlignmentZone[] readAlignmentZones(Element parentElement) { Element zonesElement = getElement("zones", parentElement); List zoneElements = zonesElement.elements("zone"); int zonesCount = zoneElements.size(); AlignmentZone[] zones = new AlignmentZone[zonesCount]; for (int i = 0; i < zonesCount; i++) { Element zoneElement = (Element) zoneElements.get(i); AlignmentZone zone = new AlignmentZone(); Attribute leftAttribute = zoneElement.attribute("left"); if (leftAttribute != null) { float left = Float.parseFloat(leftAttribute.getValue()); float width = getFloatAttribute("width", zoneElement); zone.setX(left, width); } Attribute baselineAttribute = zoneElement.attribute("baseline"); if (baselineAttribute != null) { float baseline = Float.parseFloat(baselineAttribute.getValue()); float height = getFloatAttribute("height", zoneElement); zone.setY(baseline, height); } zones[i] = zone; } return zones; } static ButtonCondAction[] readButtonCondActions(Element parentElement) { Element actionsElement = parentElement.element("actions"); if (actionsElement != null) { List actions = actionsElement.elements(); int arraySize = actions.size(); ButtonCondAction[] actionArray = new ButtonCondAction[arraySize]; for (int i = 0; i < arraySize; i++) { ButtonCondAction action = new ButtonCondAction(); Element actionElement = (Element) actions.get(i); if (getBooleanAttribute("outdowntoidle", actionElement)) { action.setOutDownToIdle(); } if (getBooleanAttribute("outdowntooverdown", actionElement)) { action.setOutDownToOverDown(); } if (getBooleanAttribute("idletooverdown", actionElement)) { action.setIdleToOverDown(); } if (getBooleanAttribute("idletooverup", actionElement)) { action.setIdleToOverUp(); } if (getBooleanAttribute("overdowntoidle", actionElement)) { action.setOverDownToIdle(); } if (getBooleanAttribute("overdowntooutdown", actionElement)) { action.setOverDownToOutDown(); } if (getBooleanAttribute("overdowntooverup", actionElement)) { action.setOverDownToOverUp(); } if (getBooleanAttribute("overuptoidle", actionElement)) { action.setOverUpToIdle(); } if (getBooleanAttribute("overuptooverdown", actionElement)) { action.setOverUpToOverDown(); } Attribute keyPress = actionElement.attribute("keypress"); if (keyPress != null) { action.setKeyPress(Byte.parseByte(keyPress.getValue())); } readActionBlock(action.getActions(), actionElement); actionArray[i] = action; } return actionArray; } return null; } static ButtonRecord[] readButtonRecords(Element parentElement) { Element charsElement = getElement("chars", parentElement); List recordElements = charsElement.elements(); int arrayLength = recordElements.size(); ButtonRecord[] records = new ButtonRecord[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element recordElement = (Element) recordElements.get(i); int charId = getIntAttribute("charid", recordElement); int depth = getIntAttribute("depth", recordElement); Element state = getElement("state", recordElement); boolean up = getBooleanAttribute("up", state); boolean down = getBooleanAttribute("down", state); boolean over = getBooleanAttribute("over", state); boolean hit = getBooleanAttribute("hit", state); Matrix placeMatrix = readMatrix("matrix", recordElement); ButtonRecord record = new ButtonRecord( charId, depth, placeMatrix, up, over, down, hit); Element colorTransform = recordElement.element("cxformwithalpha"); if (colorTransform != null) { record.setColorTransform(readCXformWithAlpha(colorTransform)); } records[i] = record; } return records; } static CXform readCXform(Element element) { CXform colorTransform = new CXform(); Element add = element.element("add"); if (add != null) { int redAdd = getIntAttribute("r", add); int greenAdd = getIntAttribute("g", add); int blueAdd = getIntAttribute("b", add); colorTransform.setAddTerms(redAdd, greenAdd, blueAdd); } Element mult = element.element("mult"); if (mult != null) { int redMult = getIntAttribute("r", mult); int greenMult = getIntAttribute("g", mult); int blueMult = getIntAttribute("b", mult); colorTransform.setMultTerms(redMult, greenMult, blueMult); } return colorTransform; } static CXformWithAlpha readCXformWithAlpha(Element element) { CXformWithAlpha colorTransform = new CXformWithAlpha(); Element add = element.element("add"); if (add != null) { int redAdd = getIntAttribute("r", add); int greenAdd = getIntAttribute("g", add); int blueAdd = getIntAttribute("b", add); int alphaAdd = getIntAttribute("a", add); colorTransform.setAddTerms(redAdd, greenAdd, blueAdd, alphaAdd); } Element mult = element.element("mult"); if (mult != null) { int redMult = getIntAttribute("r", mult); int greenMult = getIntAttribute("g", mult); int blueMult = getIntAttribute("b", mult); int alphaMult = getIntAttribute("a", mult); colorTransform.setMultTerms(redMult, greenMult, blueMult, alphaMult); } return colorTransform; } static ClipActions readClipActions(Element element) { ClipEventFlags eventFlags = readClipEventFlags(element); List recordElements = element.elements("clipactionrecord"); List records = new ArrayList(); for (Iterator it = recordElements.iterator(); it.hasNext();) { Element recordElement = (Element) it.next(); ClipActionRecord record = new ClipActionRecord( readClipEventFlags(recordElement)); Attribute keyCode = recordElement.attribute("keycode"); if (keyCode != null) { record.setKeyCode(Short.parseShort(keyCode.getValue())); } readActionBlock(record.getActions(), recordElement); records.add(record); } return new ClipActions(eventFlags, records); } static Color readColor(Element element) { if (element.attribute("a") == null) { return readRGB(element); } return readRGBA(element); } static List readFilters(Element element) { List filterElements = element.elements(); int filterCount = filterElements.size(); List filters = new ArrayList(filterCount); for (int j = 0; j < filterCount; j++) { Element filterElement = (Element) filterElements.get(j); if (filterElement.getName().equals("colormatrix")) { List valElements = filterElement.elements("val"); int valCount = valElements.size(); if (valCount != 20) { throw new MalformedElementException( "colormatrix must contain 20 values!"); } float[] matrix = new float[20]; for (int i = 0; i < 20; i++) { Element valElement = (Element) valElements.get(i); matrix[i] = Float.parseFloat(valElement.getText()); } ColorMatrixFilter colorMatrixFilter = new ColorMatrixFilter(matrix); filters.add(colorMatrixFilter); } else if (filterElement.getName().equals("convolution")) { Element matrixElement = filterElement.element("matrix"); List valElements = matrixElement.elements("val"); float[] matrix = new float[valElements.size()]; for (int i = 0; i < matrix.length; i++) { Element valElement = (Element) valElements.get(i); matrix[i] = Float.parseFloat(valElement.getText()); } int matrixRows = getIntAttribute( "rows", matrixElement); ConvolutionFilter convolutionFilter = new ConvolutionFilter( matrix, matrixRows); convolutionFilter.setColor( readRGBA(getElement("color", filterElement))); convolutionFilter.setDivisor( getFloatAttribute("divisor", filterElement)); convolutionFilter.setBias(getFloatAttribute("bias", filterElement)); convolutionFilter.setClamp(getBooleanAttribute("clamp", filterElement)); convolutionFilter.setPreserveAlpha( getBooleanAttribute("preservealpha", filterElement)); filters.add(convolutionFilter); } else if (filterElement.getName().equals("blur")) { BlurFilter blurFilter = new BlurFilter( getDoubleAttribute("x", filterElement), getDoubleAttribute("y", filterElement)); blurFilter.setQuality(getIntAttribute("quality", filterElement)); filters.add(blurFilter); } else if (filterElement.getName().equals("dropshadow")) { DropShadowFilter dropShadowFilter = new DropShadowFilter(); dropShadowFilter.setColor(readRGBA(getElement("color", filterElement))); dropShadowFilter.setX(getDoubleAttribute("x", filterElement)); dropShadowFilter.setY(getDoubleAttribute("y", filterElement)); dropShadowFilter.setAngle(getDoubleAttribute("angle", filterElement)); dropShadowFilter.setDistance( getDoubleAttribute("distance", filterElement)); dropShadowFilter.setStrength( getDoubleAttribute("strength", filterElement)); dropShadowFilter.setQuality(getIntAttribute("quality", filterElement)); dropShadowFilter.setInner(getBooleanAttribute("inner", filterElement)); dropShadowFilter.setKnockout( getBooleanAttribute("knockout", filterElement)); dropShadowFilter.setHideObject( getBooleanAttribute("hideobject", filterElement)); filters.add(dropShadowFilter); } else if (filterElement.getName().equals("glow")) { GlowFilter glowFilter = new GlowFilter(); glowFilter.setColor(readRGBA(getElement("color", filterElement))); glowFilter.setX(getDoubleAttribute("x", filterElement)); glowFilter.setY(getDoubleAttribute("y", filterElement)); glowFilter.setStrength(getDoubleAttribute("strength", filterElement)); glowFilter.setQuality(getIntAttribute("quality", filterElement)); glowFilter.setInner(getBooleanAttribute("inner", filterElement)); glowFilter.setKnockout(getBooleanAttribute("knockout", filterElement)); filters.add(glowFilter); } else if (filterElement.getName().equals("bevel")) { BevelFilter bevelFilter = new BevelFilter(); bevelFilter.setHighlightColor( readRGBA(getElement("highlightcolor", filterElement))); bevelFilter.setShadowColor( readRGBA(getElement("shadowcolor", filterElement))); bevelFilter.setX(getDoubleAttribute("x", filterElement)); bevelFilter.setY(getDoubleAttribute("y", filterElement)); bevelFilter.setAngle(getDoubleAttribute("angle", filterElement)); bevelFilter.setDistance(getDoubleAttribute("distance", filterElement)); bevelFilter.setStrength(getDoubleAttribute("strength", filterElement)); bevelFilter.setQuality(getIntAttribute("quality", filterElement)); bevelFilter.setInner(getBooleanAttribute("inner", filterElement)); bevelFilter.setKnockout(getBooleanAttribute("knockout", filterElement)); bevelFilter.setOnTop(getBooleanAttribute("ontop", filterElement)); filters.add(bevelFilter); } else if (filterElement.getName().equals("gradientglow")) { Element pointsElement = getElement("controlpoints", filterElement); List pointElements = pointsElement.elements("controlpoint"); int controlPointsCount = pointElements.size(); RGBA[] colors = new RGBA[controlPointsCount]; short[] ratios = new short[controlPointsCount]; for (int i = 0; i < controlPointsCount; i++) { Element pointElement = (Element) pointElements.get(i); colors[i] = readRGBA(getElement("color", pointElement)); ratios[i] = getShortAttribute("ratio", pointElement); } GradientGlowFilter gradientGlowFilter = new GradientGlowFilter( colors, ratios); gradientGlowFilter.setX(getDoubleAttribute("x", filterElement)); gradientGlowFilter.setY(getDoubleAttribute("y", filterElement)); gradientGlowFilter.setAngle(getDoubleAttribute("angle", filterElement)); gradientGlowFilter.setDistance( getDoubleAttribute("distance", filterElement)); gradientGlowFilter.setStrength( getDoubleAttribute("strength", filterElement)); gradientGlowFilter.setQuality( getIntAttribute("quality", filterElement)); gradientGlowFilter.setInner( getBooleanAttribute("inner", filterElement)); gradientGlowFilter.setKnockout( getBooleanAttribute("knockout", filterElement)); gradientGlowFilter.setOnTop( getBooleanAttribute("ontop", filterElement)); filters.add(gradientGlowFilter); } else if (filterElement.getName().equals("gradientbevel")) { Element pointsElement = getElement("controlpoints", filterElement); List pointElements = pointsElement.elements("controlpoint"); int controlPointsCount = pointElements.size(); RGBA[] colors = new RGBA[controlPointsCount]; short[] ratios = new short[controlPointsCount]; for (int i = 0; i < controlPointsCount; i++) { Element pointElement = (Element) pointElements.get(i); colors[i] = readRGBA(getElement("color", pointElement)); ratios[i] = getShortAttribute("ratio", pointElement); } GradientBevelFilter gradientBevelFilter = new GradientBevelFilter( colors, ratios); gradientBevelFilter.setX(getDoubleAttribute("x", filterElement)); gradientBevelFilter.setY(getDoubleAttribute("y", filterElement)); gradientBevelFilter.setAngle( getDoubleAttribute("angle", filterElement)); gradientBevelFilter.setDistance( getDoubleAttribute("distance", filterElement)); gradientBevelFilter.setStrength( getDoubleAttribute("strength", filterElement)); gradientBevelFilter.setQuality( getIntAttribute("quality", filterElement)); gradientBevelFilter.setInner( getBooleanAttribute("inner", filterElement)); gradientBevelFilter.setKnockout( getBooleanAttribute("knockout", filterElement)); gradientBevelFilter.setOnTop( getBooleanAttribute("ontop", filterElement)); filters.add(gradientBevelFilter); } } return filters; } static Matrix readMatrix(Element element) { Element translate = getElement("translate", element); int translateX = getIntAttribute("x", translate); int translateY = getIntAttribute("y", translate); Matrix matrix = new Matrix(translateX, translateY); Element rotateSkew = element.element("rotateskew"); if (rotateSkew != null) { matrix.setRotateSkew( getDoubleAttribute("rs0", rotateSkew), getDoubleAttribute("rs1", rotateSkew)); } Element scale = element.element("scale"); if (scale != null) { matrix.setScale( getDoubleAttribute("x", scale), getDoubleAttribute("y", scale)); } return matrix; } static Matrix readMatrix(String elementName, Element parentElement) { Element matrixElement = getElement(elementName, parentElement); return readMatrix(matrixElement); } static MorphFillStyle readMorphFillStyle(Element element) { Element startElement = getElement("start", element); Element endElement = getElement("end", element); String type = getStringAttribute("type", element); if (type.equals("solid")) { RGBA startColor = readRGBA(getElement("color", startElement)); RGBA endColor = readRGBA(getElement("color", endElement)); return new MorphFillStyle(startColor, endColor); } else if (type.equals("lineargradient")) { return new MorphFillStyle( readMorphGradient(element), readMatrix("gradientmatrix", startElement), readMatrix("gradientmatrix", endElement), MorphFillStyle.TYPE_LINEAR_GRADIENT); } else if (type.equals("focalradialgradient")) { return new MorphFillStyle( readMorphGradient(element), readMatrix("gradientmatrix", startElement), readMatrix("gradientmatrix", endElement), MorphFillStyle.TYPE_FOCAL_RADIAL_GRADIENT); } else if (type.equals("radialgradient")) { return new MorphFillStyle( readMorphGradient(element), readMatrix("gradientmatrix", startElement), readMatrix("gradientmatrix", endElement), MorphFillStyle.TYPE_RADIAL_GRADIENT); } else if (type.equals("tiledbitmap")) { return new MorphFillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", startElement), readMatrix("bitmapmatrix", endElement), MorphFillStyle.TYPE_TILED_BITMAP); } else if (type.equals("clippedbitmap")) { return new MorphFillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", startElement), readMatrix("bitmapmatrix", endElement), MorphFillStyle.TYPE_CLIPPED_BITMAP); } else if (type.equals("nonsmoothedtiledbitmap")) { return new MorphFillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", startElement), readMatrix("bitmapmatrix", endElement), MorphFillStyle.TYPE_NONSMOOTHED_TILED_BITMAP); } else if (type.equals("nonsmoothedclippedbitmap")) { return new MorphFillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", startElement), readMatrix("bitmapmatrix", endElement), MorphFillStyle.TYPE_NONSMOOTHED_CLIPPED_BITMAP); } else { throw new IllegalArgumentException("Illegal morph fill type: " + type); } } static MorphFillStyles readMorphFillStyles(Element parentElement) { Element element = getElement("morphfillstyles", parentElement); List styleElements = element.elements(); MorphFillStyles styles = new MorphFillStyles(); for (Iterator it = styleElements.iterator(); it.hasNext();) { Element styleElement = (Element) it.next(); styles.addStyle(readMorphFillStyle(styleElement)); } return styles; } static MorphLineStyles readMorphLineStyles(Element parentElement) { Element element = getElement("morphlinestyles", parentElement); MorphLineStyles styles = new MorphLineStyles(); List styleElements = element.elements(); for (Iterator it = styleElements.iterator(); it.hasNext();) { Element styleElement = (Element) it.next(); if (styleElement.getName().equals("morphlinestyle")) { styles.addStyle(readMorphLineStyle(styleElement)); } else if (styleElement.getName().equals("morphlinestyle2")) { styles.addStyle(readMorphLineStyle2(styleElement)); } } return styles; } static RGB readRGB(Element element) { short red = getShortAttribute("r", element); short green = getShortAttribute("g", element); short blue = getShortAttribute("b", element); return new RGB(red, green, blue); } static RGBA readRGBA(Element element) { short red = getShortAttribute("r", element); short green = getShortAttribute("g", element); short blue = getShortAttribute("b", element); short alpha = getShortAttribute("a", element); return new RGBA(red, green, blue, alpha); } static Rect readRect(Element element) { long xMin = getLongAttribute("xmin", element); long xMax = getLongAttribute("xmax", element); long yMin = getLongAttribute("ymin", element); long yMax = getLongAttribute("ymax", element); return new Rect(xMin, xMax, yMin, yMax); } static Shape readShape(Element element) { List shapeRecordElements = element.elements(); int arrayLength = shapeRecordElements.size(); ShapeRecord[] shapeRecords = new ShapeRecord[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element shapeRecordElement = (Element) shapeRecordElements.get(i); if (shapeRecordElement.getName().equals("straightedgerecord")) { shapeRecords[i] = readStraightEdgeRecord(shapeRecordElement); } else if (shapeRecordElement.getName().equals("curvededgerecord")) { shapeRecords[i] = readCurvedEdgeRecord(shapeRecordElement); } else if (shapeRecordElement.getName().equals("stylechangerecord")) { shapeRecords[i] = readStyleChangeRecord(shapeRecordElement); } } return new Shape(shapeRecords); } static ShapeWithStyle readShapeWithStyle(Element parentElement) { Element element = getElement("shapewithstyle", parentElement); Element shape = getElement("shape", element); List shapeRecordElements = shape.elements(); int arrayLength = shapeRecordElements.size(); ShapeRecord[] shapeRecords = new ShapeRecord[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element shapeRecordElement = (Element) shapeRecordElements.get(i); if (shapeRecordElement.getName().equals("straightedgerecord")) { shapeRecords[i] = readStraightEdgeRecord(shapeRecordElement); } else if (shapeRecordElement.getName().equals("curvededgerecord")) { shapeRecords[i] = readCurvedEdgeRecord(shapeRecordElement); } else if (shapeRecordElement.getName().equals("stylechangerecord")) { shapeRecords[i] = readStyleChangeRecord(shapeRecordElement); } } Element lineStyles = element.element("linestyles"); Element fillStyles = element.element("fillstyles"); return new ShapeWithStyle( readFillStyles(fillStyles), readLineStyles(lineStyles), shapeRecords); } static SoundInfo readSoundInfo(Element parentElement) { Element element = getElement("soundinfo", parentElement); SoundInfo soundInfo = new SoundInfo(); if (getBooleanAttribute("syncstop", element)) { soundInfo.setSyncStop(); } if (getBooleanAttribute("syncnomultiple", element)) { soundInfo.setSyncNoMultiple(); } Attribute loopCount = element.attribute("loopcount"); if (loopCount != null) { soundInfo.setLoopCount(Integer.parseInt(loopCount.getValue())); } Attribute inPoint = element.attribute("inpoint"); if (inPoint != null) { soundInfo.setInPoint(Integer.parseInt(inPoint.getValue())); } Element envelopeRecordsElement = element.element("enveloperecords"); if (envelopeRecordsElement != null) { soundInfo.setEnvelopeRecords( readSoundEnvelopeRecords(envelopeRecordsElement)); } return soundInfo; } static TextRecord[] readTextRecords(Element parentElement) { Element element = getElement("textrecords", parentElement); List recordElements = element.elements(); int arrayLength = recordElements.size(); TextRecord[] records = new TextRecord[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element recordElement = (Element) recordElements.get(i); GlyphEntry[] glyphEntries = readGlyphEntries(recordElement); TextRecord record = new TextRecord(glyphEntries); Attribute fontId = recordElement.attribute("fontid"); if (fontId != null) { record.setFont( Integer.parseInt(fontId.getValue()), getIntAttribute("height", recordElement)); } Attribute xOffset = recordElement.attribute("xoffset"); if (xOffset != null) { record.setXOffset(Short.parseShort(xOffset.getValue())); } Attribute yOffset = recordElement.attribute("yoffset"); if (yOffset != null) { record.setYOffset(Short.parseShort(yOffset.getValue())); } Element color = recordElement.element("color"); if (color != null) { record.setTextColor(RecordXMLReader.readColor(color)); } records[i] = record; } return records; } static ZlibBitmapData readZlibBitmapData(Element parentElement) { // transparency not supported Element element = parentElement.element("bitmapdata"); if (element != null) { return new BitmapData(readBitmapPixelData(element)); } element = parentElement.element("colormapdata"); if (element != null) { Element colorTableElement = getElement("colortable", element); RGB[] colorTable = readRGBArray(colorTableElement); Element pixelDataElement = getElement("pixeldata", element); short[] pixelData = Base64.decodeUnsigned( pixelDataElement.getText()); return new ColorMapData(colorTable, pixelData); } throw new MissingNodeException( "Element " + parentElement.getPath() + " must contain either a bitmapdata or a colormapdata element!"); } static ZlibBitmapData readZlibBitmapData2(Element parentElement) { // transparency supported Element element = parentElement.element("alphabitmapdata"); if (element != null) { return new AlphaBitmapData(readRGBAArray(element)); } element = parentElement.element("alphacolormapdata"); if (element != null) { Element colorTableElement = getElement("colortable", element); RGBA[] colorTable = readRGBAArray(colorTableElement); Element pixelDataElement = getElement("pixeldata", element); short[] pixelData = Base64.decodeUnsigned( pixelDataElement.getText()); return new AlphaColorMapData(colorTable, pixelData); } throw new MissingNodeException( "Element " + parentElement.getPath() + " must contain either an alphabitmapdata or an alphacolormapdata element!"); } private static BitmapPixelData[] readBitmapPixelData(Element parentElement) { Element element = parentElement.element("pix15array"); if (element != null) { byte[] buffer = Base64.decode(element.getText()); int arrayLength = buffer.length / 3; Pix15[] array = new Pix15[arrayLength]; for (int i = 0; i < arrayLength; i++) { int j = i * 3; array[i] = new Pix15(buffer[j], buffer[j + 1], buffer[j + 2]); } return array; } element = parentElement.element("pix24array"); if (element != null) { short[] buffer = Base64.decodeUnsigned(element.getText()); int arrayLength = buffer.length / 3; Pix24[] array = new Pix24[arrayLength]; for (int i = 0; i < arrayLength; i++) { int j = i * 3; array[i] = new Pix24(buffer[j], buffer[j + 1], buffer[j + 2]); } return array; } throw new MissingNodeException( "Element " + parentElement.getPath() + " must contain either a pix15array or a pix24array element!"); } private static byte readCapStyle(String attrName, Element element) { String capStyle = getStringAttribute(attrName, element); if (capStyle.equals("none")) { return EnhancedStrokeStyle.CAPS_NONE; } if (capStyle.equals("round")) { return EnhancedStrokeStyle.CAPS_ROUND; } if (capStyle.equals("square")) { return EnhancedStrokeStyle.CAPS_SQUARE; } return -1; } private static ClipEventFlags readClipEventFlags(Element parentElement) { Element element = getElement("clipeventflags", parentElement); ClipEventFlags clipEventFlags = new ClipEventFlags(); if (getBooleanAttribute("keyup", element)) { clipEventFlags.setKeyUp(); } if (getBooleanAttribute("keydown", element)) { clipEventFlags.setKeyDown(); } if (getBooleanAttribute("keypress", element)) { clipEventFlags.setKeyPress(); } if (getBooleanAttribute("mouseup", element)) { clipEventFlags.setMouseUp(); } if (getBooleanAttribute("mousedown", element)) { clipEventFlags.setMouseDown(); } if (getBooleanAttribute("mousemove", element)) { clipEventFlags.setMouseMove(); } if (getBooleanAttribute("load", element)) { clipEventFlags.setLoad(); } if (getBooleanAttribute("unload", element)) { clipEventFlags.setUnload(); } if (getBooleanAttribute("enterframe", element)) { clipEventFlags.setEnterFrame(); } if (getBooleanAttribute("dragover", element)) { clipEventFlags.setDragOver(); } if (getBooleanAttribute("dragout", element)) { clipEventFlags.setDragOut(); } if (getBooleanAttribute("rollover", element)) { clipEventFlags.setRollOver(); } if (getBooleanAttribute("rollout", element)) { clipEventFlags.setRollOut(); } if (getBooleanAttribute("releaseoutside", element)) { clipEventFlags.setReleaseOutside(); } if (getBooleanAttribute("release", element)) { clipEventFlags.setRelease(); } if (getBooleanAttribute("press", element)) { clipEventFlags.setPress(); } if (getBooleanAttribute("initialize", element)) { clipEventFlags.setInitialize(); } if (getBooleanAttribute("data", element)) { clipEventFlags.setData(); } if (getBooleanAttribute("construct", element)) { clipEventFlags.setConstruct(); } return clipEventFlags; } private static ShapeRecord readCurvedEdgeRecord(Element element) { int anchorDeltaX = getIntAttribute("anchordx", element); int anchorDeltaY = getIntAttribute("anchordy", element); int controlDeltaX = getIntAttribute("controldx", element); int controlDeltaY = getIntAttribute("controldy", element); return new CurvedEdgeRecord( controlDeltaX, controlDeltaY, anchorDeltaX, anchorDeltaY); } private static FillStyle readFillStyle(Element element) { String type = getStringAttribute("type", element); if (type.equals("solid")) { Color color = readColor(getElement("color", element)); return new FillStyle(color); } else if (type.equals("lineargradient")) { return new FillStyle( readGradient(element), readMatrix("gradientmatrix", element), FillStyle.TYPE_LINEAR_GRADIENT); } else if (type.equals("focalradialgradient")) { return new FillStyle( readGradient(element), readMatrix("gradientmatrix", element), FillStyle.TYPE_FOCAL_RADIAL_GRADIENT); } else if (type.equals("radialgradient")) { return new FillStyle( readGradient(element), readMatrix("gradientmatrix", element), FillStyle.TYPE_RADIAL_GRADIENT); } else if (type.equals("tiledbitmap")) { return new FillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", element), FillStyle.TYPE_TILED_BITMAP); } else if (type.equals("clippedbitmap")) { return new FillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", element), FillStyle.TYPE_CLIPPED_BITMAP); } else if (type.equals("nonsmoothedtiledbitmap")) { return new FillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", element), FillStyle.TYPE_NONSMOOTHED_TILED_BITMAP); } else if (type.equals("nonsmoothedclippedbitmap")) { return new FillStyle( getIntAttribute("bitmapid", element), readMatrix("bitmapmatrix", element), FillStyle.TYPE_NONSMOOTHED_CLIPPED_BITMAP); } else { throw new IllegalArgumentException("Illegal fill type: " + type); } } private static FillStyleArray readFillStyles(Element element) { List styleElements = element.elements(); FillStyleArray styleArray = new FillStyleArray(); for (Iterator it = styleElements.iterator(); it.hasNext();) { Element styleElement = (Element) it.next(); styleArray.addStyle(readFillStyle(styleElement)); } return styleArray; } private static GlyphEntry[] readGlyphEntries(Element parentElement) { Element element = getElement("glyphentries", parentElement); List entryElements = element.elements(); int arrayLength = entryElements.size(); GlyphEntry[] entries = new GlyphEntry[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element entryElement = (Element) entryElements.get(i); entries[i] = new GlyphEntry( getIntAttribute("index", entryElement), getIntAttribute("advance", entryElement)); } return entries; } private static Gradient readGradient(Element parentElement) { Element element = parentElement.element("gradient"); boolean focal = false; if (element == null) { element = getElement("focalgradient", parentElement); focal = true; } List recordElements = element.elements("gradrecord"); int arrayLength = recordElements.size(); GradRecord[] records = new GradRecord[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element recordElement = (Element) recordElements.get(i); records[i] = new GradRecord( getShortAttribute("ratio", recordElement), readColor(getElement("color", recordElement))); } Gradient gradient; if (focal) { gradient = new FocalGradient( records, getDoubleAttribute("focalpointratio", element)); } else { gradient = new Gradient(records); } gradient.setInterpolationMethod(readInterpolationMethod(element)); gradient.setSpreadMethod(readSpreadMethod(element)); return gradient; } private static byte readInterpolationMethod(Element element) { String interpolation = getStringAttribute("interpolation", element); if (interpolation.equals("linear-rgb")) { return Gradient.INTERPOLATION_LINEAR_RGB; } else if (interpolation.equals("rgb")) { return Gradient.INTERPOLATION_RGB; } return -1; } private static byte readJointStyle(Element element) { String jointStyle = getStringAttribute("joint", element); if (jointStyle.equals("round")) { return EnhancedStrokeStyle.JOINT_ROUND; } if (jointStyle.equals("miter")) { return EnhancedStrokeStyle.JOINT_ROUND; } if (jointStyle.equals("bevel")) { return EnhancedStrokeStyle.JOINT_ROUND; } return -1; } private static LineStyle readLineStyle(Element element) { int width = getIntAttribute("width", element); Color color = readColor(getElement("color", element)); return new LineStyle(width, color); } private static LineStyle2 readLineStyle2(Element element) { LineStyle2 lineStyle2 = new LineStyle2(getIntAttribute("width", element)); byte jointStyle = readJointStyle(element); lineStyle2.setJointStyle(jointStyle); if (jointStyle == EnhancedStrokeStyle.JOINT_MITER) { lineStyle2.setMiterLimit(getDoubleAttribute("miterlimit", element)); } Element capStyleElement = getElement("capstyle", element); lineStyle2.setStartCapStyle(readCapStyle("start", capStyleElement)); lineStyle2.setStartCapStyle(readCapStyle("end", capStyleElement)); lineStyle2.setScaleStroke(readScaleStroke(element)); lineStyle2.setClose(getBooleanAttribute("close", element)); lineStyle2.setPixelHinting(getBooleanAttribute("pixelhinting", element)); Element fillStyleElement = element.element("fillstyle"); if (fillStyleElement == null) { Element colorElement = getElement("color", element); lineStyle2.setColor(readRGBA(colorElement)); } else { lineStyle2.setFillStyle(readFillStyle(fillStyleElement)); } return lineStyle2; } private static LineStyleArray readLineStyles(Element element) { LineStyleArray styleArray = new LineStyleArray(); List styleElements = element.elements(); for (Iterator it = styleElements.iterator(); it.hasNext();) { Element styleElement = (Element) it.next(); if (styleElement.getName().equals("linestyle")) { styleArray.addStyle(readLineStyle(styleElement)); } else if (styleElement.getName().equals("linestyle2")) { styleArray.addStyle(readLineStyle2(styleElement)); } } return styleArray; } private static MorphGradient readMorphGradient(Element parentElement) { Element element = parentElement.element("morphgradient"); boolean focal = false; if (element == null) { element = getElement("focalmorphgradient", parentElement); focal = true; } List recordElements = element.elements("morphgradrecord"); int arrayLength = recordElements.size(); MorphGradRecord[] records = new MorphGradRecord[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element recordElement = (Element) recordElements.get(i); Element start = getElement("start", recordElement); short startRatio = getShortAttribute("ratio", start); RGBA startColor = readRGBA(getElement("color", start)); Element end = getElement("end", recordElement); short endRatio = getShortAttribute("ratio", end); RGBA endColor = readRGBA(getElement("color", end)); records[i] = new MorphGradRecord( startRatio, startColor, endRatio, endColor); } MorphGradient morphGradient; if (focal) { double startFocalpointratio = getDoubleAttribute( "startfocalpointratio", element); double endfocalpointratio = getDoubleAttribute( "endfocalpointratio", element); morphGradient = new FocalMorphGradient( records, startFocalpointratio, endfocalpointratio); } else { morphGradient = new MorphGradient(records); } morphGradient.setInterpolationMethod(readInterpolationMethod(element)); morphGradient.setSpreadMethod(readSpreadMethod(element)); return morphGradient; } private static MorphLineStyle readMorphLineStyle(Element element) { Element startElement = getElement("start", element); int startWidth = getIntAttribute("width", startElement); RGBA startColor = readRGBA(getElement("color", startElement)); Element endElement = getElement("end", element); int endWidth = getIntAttribute("width", endElement); RGBA endColor = readRGBA(getElement("color", endElement)); return new MorphLineStyle(startWidth, startColor, endWidth, endColor); } private static MorphLineStyle2 readMorphLineStyle2(Element element) { Element startElement = getElement("start", element); int startWidth = getIntAttribute("width", startElement); Element endElement = getElement("end", element); int endWidth = getIntAttribute("width", endElement); MorphLineStyle2 lineStyle2; Element fillStyleElement = element.element("morphfillstyle"); if (fillStyleElement == null) { RGBA startColor = readRGBA(getElement("color", startElement)); RGBA endColor = readRGBA(getElement("color", endElement)); lineStyle2 = new MorphLineStyle2( startWidth, startColor, endWidth, endColor); } else { MorphFillStyle fillStyle = readMorphFillStyle(fillStyleElement); lineStyle2 = new MorphLineStyle2(startWidth, endWidth, fillStyle); } byte jointStyle = readJointStyle(element); lineStyle2.setJointStyle(jointStyle); if (jointStyle == EnhancedStrokeStyle.JOINT_MITER) { lineStyle2.setMiterLimit(getDoubleAttribute("miterlimit", element)); } Element capStyleElement = getElement("capstyle", element); lineStyle2.setStartCapStyle(readCapStyle("start", capStyleElement)); lineStyle2.setStartCapStyle(readCapStyle("end", capStyleElement)); lineStyle2.setScaleStroke(readScaleStroke(element)); lineStyle2.setClose(getBooleanAttribute("close", element)); lineStyle2.setPixelHinting(getBooleanAttribute("pixelhinting", element)); return lineStyle2; } private static RGBA[] readRGBAArray(Element parentElement) { Element rgbaArrayElement = getElement("rgbaarray", parentElement); short[] buffer = Base64.decodeUnsigned( rgbaArrayElement.getText()); int arrayLength = buffer.length / 4; RGBA[] rgbaArray = new RGBA[arrayLength]; for (int i = 0; i < arrayLength; i++) { int j = i * 4; rgbaArray[i] = new RGBA( buffer[j], buffer[j + 1], buffer[j + 2], buffer[j + 3]); } return rgbaArray; } private static RGB[] readRGBArray(Element parentElement) { Element rgbArrayElement = getElement("rgbarray", parentElement); short[] buffer = Base64.decodeUnsigned(rgbArrayElement.getText()); int arrayLength = buffer.length / 3; RGB[] rgbArray = new RGB[arrayLength]; for (int i = 0; i < arrayLength; i++) { int j = i * 3; rgbArray[i] = new RGB(buffer[j], buffer[j + 1], buffer[j + 2]); } return rgbArray; } private static byte readScaleStroke(Element element) { String scaleStroke = getStringAttribute("scalestroke", element); if (scaleStroke.equals("none")) { return EnhancedStrokeStyle.SCALE_NONE; } else if (scaleStroke.equals("horizontal")) { return EnhancedStrokeStyle.SCALE_HORIZONTAL; } else if (scaleStroke.equals("vertical")) { return EnhancedStrokeStyle.SCALE_VERTICAL; } else if (scaleStroke.equals("both")) { return EnhancedStrokeStyle.SCALE_BOTH; } return -1; } private static SoundEnvelope[] readSoundEnvelopeRecords( Element parentElement) { List recordElements = parentElement.elements(); int arrayLength = recordElements.size(); SoundEnvelope[] records = new SoundEnvelope[arrayLength]; for (int i = 0; i < arrayLength; i++) { Element recordElement = (Element) recordElements.get(i); long pos44 = getLongAttribute("pos44", recordElement); int leftLevel = getIntAttribute("leftlevel", recordElement); int rightLevel = getIntAttribute("rightlevel", recordElement); SoundEnvelope record = new SoundEnvelope(pos44, leftLevel, rightLevel); records[i] = record; } return records; } private static byte readSpreadMethod(Element element) { String spread = getStringAttribute("spread", element); if (spread.equals("pad")) { return Gradient.SPREAD_PAD; } else if (spread.equals("reflect")) { return Gradient.SPREAD_REFLECT; } else if (spread.equals("repeat")) { return Gradient.SPREAD_REPEAT; } return -1; } private static ShapeRecord readStraightEdgeRecord(Element element) { int deltaX = getIntAttribute("dx", element); int deltaY = getIntAttribute("dy", element); return new StraightEdgeRecord(deltaX, deltaY); } private static ShapeRecord readStyleChangeRecord(Element element) { StyleChangeRecord record = new StyleChangeRecord(); Element moveTo = element.element("moveto"); if (moveTo != null) { record.setMoveTo( getIntAttribute("x", moveTo), getIntAttribute("y", moveTo)); } Element styles = element.element("styles"); if (styles != null) { Attribute line = styles.attribute("line"); if (line != null) { record.setLineStyle(Integer.parseInt(line.getValue())); } Attribute fill0 = styles.attribute("fill0"); if (fill0 != null) { record.setFillStyle0(Integer.parseInt(fill0.getValue())); } Attribute fill1 = styles.attribute("fill1"); if (fill1 != null) { record.setFillStyle1(Integer.parseInt(fill1.getValue())); } Element newLineStyles = styles.element("linestyles"); if (newLineStyles != null) { // new line styles always come together with new fill styles Element newFillStyles = getElement("fillstyles", styles); record.setNewStyles( readLineStyles(newLineStyles), readFillStyles(newFillStyles)); } } return record; } }