/* * 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.BlendMode; import com.jswiff.swfrecords.ButtonCondAction; import com.jswiff.swfrecords.ButtonRecord; import com.jswiff.swfrecords.CXform; import com.jswiff.swfrecords.KerningRecord; import com.jswiff.swfrecords.LangCode; import com.jswiff.swfrecords.MorphFillStyles; import com.jswiff.swfrecords.MorphLineStyles; import com.jswiff.swfrecords.Shape; import com.jswiff.swfrecords.TextRecord; import com.jswiff.swfrecords.tags.DefineBits; import com.jswiff.swfrecords.tags.DefineBitsJPEG2; import com.jswiff.swfrecords.tags.DefineBitsJPEG3; import com.jswiff.swfrecords.tags.DefineBitsLossless; import com.jswiff.swfrecords.tags.DefineBitsLossless2; import com.jswiff.swfrecords.tags.DefineButton; import com.jswiff.swfrecords.tags.DefineButton2; import com.jswiff.swfrecords.tags.DefineButtonCXform; import com.jswiff.swfrecords.tags.DefineButtonSound; import com.jswiff.swfrecords.tags.DefineEditText; import com.jswiff.swfrecords.tags.DefineFont; import com.jswiff.swfrecords.tags.DefineFont2; import com.jswiff.swfrecords.tags.DefineFont3; import com.jswiff.swfrecords.tags.DefineFontAlignment; import com.jswiff.swfrecords.tags.DefineFontInfo; import com.jswiff.swfrecords.tags.DefineFontInfo2; import com.jswiff.swfrecords.tags.DefineMorphShape; import com.jswiff.swfrecords.tags.DefineMorphShape2; import com.jswiff.swfrecords.tags.DefineShape; import com.jswiff.swfrecords.tags.DefineShape2; import com.jswiff.swfrecords.tags.DefineShape3; import com.jswiff.swfrecords.tags.DefineShape4; import com.jswiff.swfrecords.tags.DefineSound; import com.jswiff.swfrecords.tags.DefineSprite; import com.jswiff.swfrecords.tags.DefineText; import com.jswiff.swfrecords.tags.DefineText2; import com.jswiff.swfrecords.tags.DefineVideoStream; import com.jswiff.swfrecords.tags.DoAction; import com.jswiff.swfrecords.tags.DoInitAction; import com.jswiff.swfrecords.tags.EnableDebugger; import com.jswiff.swfrecords.tags.EnableDebugger2; import com.jswiff.swfrecords.tags.ExportAssets; import com.jswiff.swfrecords.tags.FlashTypeSettings; import com.jswiff.swfrecords.tags.FrameLabel; import com.jswiff.swfrecords.tags.FreeCharacter; import com.jswiff.swfrecords.tags.ImportAssets; import com.jswiff.swfrecords.tags.ImportAssets2; import com.jswiff.swfrecords.tags.JPEGTables; import com.jswiff.swfrecords.tags.MalformedTag; import com.jswiff.swfrecords.tags.PlaceObject; import com.jswiff.swfrecords.tags.PlaceObject2; import com.jswiff.swfrecords.tags.PlaceObject3; import com.jswiff.swfrecords.tags.Protect; import com.jswiff.swfrecords.tags.RemoveObject; import com.jswiff.swfrecords.tags.RemoveObject2; import com.jswiff.swfrecords.tags.Scale9Grid; import com.jswiff.swfrecords.tags.ScriptLimits; import com.jswiff.swfrecords.tags.SetTabIndex; import com.jswiff.swfrecords.tags.ShowFrame; import com.jswiff.swfrecords.tags.SoundStreamBlock; import com.jswiff.swfrecords.tags.SoundStreamHead; import com.jswiff.swfrecords.tags.SoundStreamHead2; import com.jswiff.swfrecords.tags.StartSound; import com.jswiff.swfrecords.tags.Tag; import com.jswiff.swfrecords.tags.TagConstants; import com.jswiff.swfrecords.tags.UnknownTag; import com.jswiff.swfrecords.tags.VideoFrame; import com.jswiff.util.Base64; import com.jswiff.util.StringUtilities; import org.dom4j.Element; import java.util.Iterator; /* * Writes SWF tags to XML. */ class TagXMLWriter { static void writeTag(Element parentElement, Tag tag) { int tagCode = tag.getCode(); switch (tagCode) { case TagConstants.DEFINE_BITS: writeDefineBits(parentElement, (DefineBits) tag); break; case TagConstants.DEFINE_BITS_JPEG_2: writeDefineBitsJPEG2(parentElement, (DefineBitsJPEG2) tag); break; case TagConstants.DEFINE_BITS_JPEG_3: writeDefineBitsJPEG3(parentElement, (DefineBitsJPEG3) tag); break; case TagConstants.DEFINE_BITS_LOSSLESS: writeDefineBitsLossless(parentElement, (DefineBitsLossless) tag); break; case TagConstants.DEFINE_BITS_LOSSLESS_2: writeDefineBitsLossless2(parentElement, (DefineBitsLossless2) tag); break; case TagConstants.DEFINE_BUTTON: writeDefineButton(parentElement, (DefineButton) tag); break; case TagConstants.DEFINE_BUTTON_2: writeDefineButton2(parentElement, (DefineButton2) tag); break; case TagConstants.DEFINE_BUTTON_C_XFORM: writeDefineButtonCXform(parentElement, (DefineButtonCXform) tag); break; case TagConstants.DEFINE_BUTTON_SOUND: writeDefineButtonSound(parentElement, (DefineButtonSound) tag); break; case TagConstants.DEFINE_EDIT_TEXT: writeDefineEditText(parentElement, (DefineEditText) tag); break; case TagConstants.DEFINE_FONT: writeDefineFont(parentElement, (DefineFont) tag); break; case TagConstants.DEFINE_FONT_2: writeDefineFont2(parentElement, (DefineFont2) tag); break; case TagConstants.DEFINE_FONT_3: writeDefineFont3(parentElement, (DefineFont3) tag); break; case TagConstants.DEFINE_FONT_INFO: writeDefineFontInfo(parentElement, (DefineFontInfo) tag); break; case TagConstants.DEFINE_FONT_INFO_2: writeDefineFontInfo2(parentElement, (DefineFontInfo2) tag); break; case TagConstants.DEFINE_FONT_ALIGNMENT: writeDefineFontAlignment(parentElement, (DefineFontAlignment) tag); break; case TagConstants.FLASHTYPE_SETTINGS: writeFlashTypeSettings(parentElement, (FlashTypeSettings) tag); break; case TagConstants.DEFINE_MORPH_SHAPE: writeDefineMorphShape(parentElement, (DefineMorphShape) tag); break; case TagConstants.DEFINE_MORPH_SHAPE_2: writeDefineMorphShape2(parentElement, (DefineMorphShape2) tag); break; case TagConstants.DEFINE_SHAPE: writeDefineShape(parentElement, (DefineShape) tag); break; case TagConstants.DEFINE_SHAPE_2: writeDefineShape2(parentElement, (DefineShape2) tag); break; case TagConstants.DEFINE_SHAPE_3: writeDefineShape3(parentElement, (DefineShape3) tag); break; case TagConstants.DEFINE_SHAPE_4: writeDefineShape4(parentElement, (DefineShape4) tag); break; case TagConstants.DEFINE_SOUND: writeDefineSound(parentElement, (DefineSound) tag); break; case TagConstants.DEFINE_SPRITE: writeDefineSprite(parentElement, (DefineSprite) tag); break; case TagConstants.DEFINE_TEXT: writeDefineText(parentElement, (DefineText) tag); break; case TagConstants.DEFINE_TEXT_2: writeDefineText2(parentElement, (DefineText2) tag); break; case TagConstants.DEFINE_VIDEO_STREAM: writeDefineVideoStream(parentElement, (DefineVideoStream) tag); break; case TagConstants.DO_ACTION: writeDoAction(parentElement, (DoAction) tag); break; case TagConstants.DO_INIT_ACTION: writeDoInitAction(parentElement, (DoInitAction) tag); break; case TagConstants.ENABLE_DEBUGGER: writeEnableDebugger(parentElement, (EnableDebugger) tag); break; case TagConstants.ENABLE_DEBUGGER_2: writeEnableDebugger2(parentElement, (EnableDebugger2) tag); break; case TagConstants.EXPORT_ASSETS: writeExportAssets(parentElement, (ExportAssets) tag); break; case TagConstants.FRAME_LABEL: writeFrameLabel(parentElement, (FrameLabel) tag); break; case TagConstants.FREE_CHARACTER: writeFreeCharacter(parentElement, (FreeCharacter) tag); break; case TagConstants.IMPORT_ASSETS: writeImportAssets(parentElement, (ImportAssets) tag); break; case TagConstants.IMPORT_ASSETS_2: writeImportAssets2(parentElement, (ImportAssets2) tag); break; case TagConstants.JPEG_TABLES: writeJPEGTables(parentElement, (JPEGTables) tag); break; case TagConstants.MALFORMED: writeMalformedTag(parentElement, (MalformedTag) tag); break; case TagConstants.PLACE_OBJECT: writePlaceObject(parentElement, (PlaceObject) tag); break; case TagConstants.PLACE_OBJECT_2: writePlaceObject2(parentElement, (PlaceObject2) tag); break; case TagConstants.PLACE_OBJECT_3: writePlaceObject3(parentElement, (PlaceObject3) tag); break; case TagConstants.PROTECT: writeProtect(parentElement, (Protect) tag); break; case TagConstants.REMOVE_OBJECT: writeRemoveObject(parentElement, (RemoveObject) tag); break; case TagConstants.REMOVE_OBJECT_2: writeRemoveObject2(parentElement, (RemoveObject2) tag); break; case TagConstants.SCRIPT_LIMITS: writeScriptLimits(parentElement, (ScriptLimits) tag); break; case TagConstants.SET_TAB_INDEX: writeSetTabIndex(parentElement, (SetTabIndex) tag); break; case TagConstants.SHOW_FRAME: writeShowFrame(parentElement, (ShowFrame) tag); break; case TagConstants.SCALE_9_GRID: writeScale9Grid(parentElement, (Scale9Grid) tag); break; case TagConstants.SOUND_STREAM_BLOCK: writeSoundStreamBlock(parentElement, (SoundStreamBlock) tag); break; case TagConstants.SOUND_STREAM_HEAD: writeSoundStreamHead(parentElement, (SoundStreamHead) tag); break; case TagConstants.SOUND_STREAM_HEAD_2: writeSoundStreamHead2(parentElement, (SoundStreamHead2) tag); break; case TagConstants.START_SOUND: writeStartSound(parentElement, (StartSound) tag); break; case TagConstants.VIDEO_FRAME: writeVideoFrame(parentElement, (VideoFrame) tag); break; default: writeUnknownTag(parentElement, (UnknownTag) tag); } } private static String getSoundFormatString(byte format) { switch (format) { case DefineSound.FORMAT_ADPCM: return "adpcm"; case DefineSound.FORMAT_MP3: return "mp3"; case DefineSound.FORMAT_NELLYMOSER: return "nellymoser"; case DefineSound.FORMAT_UNCOMPRESSED: return "uncompressed"; case DefineSound.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN: return "uncompressedle"; default: throw new IllegalArgumentException("Illegal sound format: " + format); } } private static String getSoundRateString(byte rate) { switch (rate) { case DefineSound.RATE_5500_HZ: return "5500"; case DefineSound.RATE_11000_HZ: return "11000"; case DefineSound.RATE_22000_HZ: return "22000"; case DefineSound.RATE_44000_HZ: return "44000"; default: throw new IllegalArgumentException("Illegal sound rate: " + rate); } } private static void writeDefineBits(Element parentElement, DefineBits tag) { Element element = parentElement.addElement("definebits"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addElement("jpegdata").addText(Base64.encode(tag.getJpegData())); } private static void writeDefineBitsJPEG2( Element parentElement, DefineBitsJPEG2 tag) { Element element = parentElement.addElement("definebitsjpeg2"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addElement("jpegdata").addText(Base64.encode(tag.getJpegData())); } private static void writeDefineBitsJPEG3( Element parentElement, DefineBitsJPEG3 tag) { Element element = parentElement.addElement("definebitsjpeg3"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addElement("jpegdata").addText(Base64.encode(tag.getJpegData())); element.addElement("alphadata").addText( Base64.encode(tag.getBitmapAlphaData())); } private static void writeDefineBitsLossless( Element parentElement, DefineBitsLossless tag) { Element element = parentElement.addElement("definebitslossless"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); String format; switch (tag.getFormat()) { case DefineBitsLossless.FORMAT_8_BIT_COLORMAPPED: format = "8bit"; break; case DefineBitsLossless.FORMAT_15_BIT_RGB: format = "15bit"; break; case DefineBitsLossless.FORMAT_24_BIT_RGB: format = "24bit"; break; default: throw new IllegalArgumentException( "Illegal lossless bitmap format: " + tag.getFormat()); } element.addAttribute("format", format); element.addAttribute("width", Integer.toString(tag.getWidth())); element.addAttribute("height", Integer.toString(tag.getHeight())); RecordXMLWriter.writeZlibBitmapData(element, tag.getZlibBitmapData()); } private static void writeDefineBitsLossless2( Element parentElement, DefineBitsLossless2 tag) { Element element = parentElement.addElement("definebitslossless2"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); String format; switch (tag.getFormat()) { case DefineBitsLossless2.FORMAT_8_BIT_COLORMAPPED: format = "8bit"; break; case DefineBitsLossless2.FORMAT_32_BIT_RGBA: format = "32bit"; break; default: throw new IllegalArgumentException( "Illegal lossless bitmap format: " + tag.getFormat()); } element.addAttribute("format", format); element.addAttribute("width", Integer.toString(tag.getWidth())); element.addAttribute("height", Integer.toString(tag.getHeight())); RecordXMLWriter.writeZlibBitmapData(element, tag.getZlibBitmapData()); } private static void writeDefineButton( Element parentElement, DefineButton tag) { Element element = parentElement.addElement("definebutton"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); Element charsElement = element.addElement("chars"); ButtonRecord[] characters = tag.getCharacters(); for (int i = 0; i < characters.length; i++) { RecordXMLWriter.writeButtonRecord(charsElement, characters[i]); } RecordXMLWriter.writeActionBlock(element, tag.getActions()); } private static void writeDefineButton2( Element parentElement, DefineButton2 tag) { Element element = parentElement.addElement("definebutton2"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); if (tag.isTrackAsMenu()) { element.addAttribute("trackasmenu", "true"); } Element charsElement = element.addElement("chars"); ButtonRecord[] characters = tag.getCharacters(); for (int i = 0; i < characters.length; i++) { RecordXMLWriter.writeButtonRecord(charsElement, characters[i]); } Element actionsElement = element.addElement("actions"); ButtonCondAction[] actions = tag.getActions(); if (actions != null) { for (int i = 0; i < actions.length; i++) { RecordXMLWriter.writeButtonCondAction(actionsElement, actions[i]); } } } private static void writeDefineButtonCXform( Element parentElement, DefineButtonCXform tag) { Element element = parentElement.addElement("definebuttoncxform"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeCXForm(element, tag.getColorTransform()); } private static void writeDefineButtonSound( Element parentElement, DefineButtonSound tag) { Element element = parentElement.addElement("definebuttonsound"); element.addAttribute("buttonid", Integer.toString(tag.getButtonId())); if (tag.getOverUpToIdleSoundId() != 0) { Element overUpToIdle = element.addElement("overuptoidle"); overUpToIdle.addAttribute( "soundid", Integer.toString(tag.getOverUpToIdleSoundId())); RecordXMLWriter.writeSoundInfo( overUpToIdle, tag.getOverUpToIdleSoundInfo()); } if (tag.getIdleToOverUpSoundId() != 0) { Element idleToOverUp = element.addElement("idletooverup"); idleToOverUp.addAttribute( "soundid", Integer.toString(tag.getIdleToOverUpSoundId())); RecordXMLWriter.writeSoundInfo( idleToOverUp, tag.getIdleToOverUpSoundInfo()); } if (tag.getOverUpToOverDownSoundId() != 0) { Element overUpToOverDown = element.addElement("overuptooverdown"); overUpToOverDown.addAttribute( "soundid", Integer.toString(tag.getOverUpToOverDownSoundId())); RecordXMLWriter.writeSoundInfo( overUpToOverDown, tag.getOverUpToOverDownSoundInfo()); } if (tag.getOverDownToOverUpSoundId() != 0) { Element overDownToOverUp = element.addElement("overdowntooverup"); overDownToOverUp.addAttribute( "soundid", Integer.toString(tag.getOverDownToOverUpSoundId())); RecordXMLWriter.writeSoundInfo( overDownToOverUp, tag.getOverDownToOverUpSoundInfo()); } } private static void writeDefineEditText( Element parentElement, DefineEditText tag) { Element element = parentElement.addElement("defineedittext"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); if (tag.isWordWrap()) { element.addAttribute("wordwrap", "true"); } if (tag.isMultiline()) { element.addAttribute("multiline", "true"); } if (tag.isPassword()) { element.addAttribute("password", "true"); } if (tag.isReadOnly()) { element.addAttribute("readonly", "true"); } if (tag.isAutoSize()) { element.addAttribute("autosize", "true"); } if (tag.isNoSelect()) { element.addAttribute("noselect", "true"); } if (tag.isBorder()) { element.addAttribute("border", "true"); } if (tag.isHtml()) { element.addAttribute("html", "true"); } if (tag.isUseOutlines()) { element.addAttribute("useoutlines", "true"); } if (tag.hasMaxLength()) { element.addAttribute("maxlength", Integer.toString(tag.getMaxLength())); } String var = tag.getVariableName(); if ((var != null) && (var.length() > 0)) { element.addAttribute("variable", var); } RecordXMLWriter.writeRect(element, "bounds", tag.getBounds()); if (tag.hasText()) { element.addElement("initialtext").addText(tag.getInitialText()); } if (tag.hasTextColor()) { RecordXMLWriter.writeRGBA(element, "color", tag.getTextColor()); } if (tag.hasFont()) { Element font = element.addElement("font"); font.addAttribute("fontid", Integer.toString(tag.getFontId())); font.addAttribute("height", Integer.toString(tag.getFontHeight())); } if (tag.hasLayout()) { Element layout = element.addElement("layout"); String align; switch (tag.getAlign()) { case DefineEditText.ALIGN_LEFT: align = "left"; break; case DefineEditText.ALIGN_CENTER: align = "center"; break; case DefineEditText.ALIGN_JUSTIFY: align = "justify"; break; case DefineEditText.ALIGN_RIGHT: align = "right"; break; default: throw new IllegalArgumentException( "Illegal text alignment: " + tag.getAlign()); } layout.addAttribute("align", align); layout.addAttribute("leftmargin", Integer.toString(tag.getLeftMargin())); layout.addAttribute( "rightmargin", Integer.toString(tag.getRightMargin())); layout.addAttribute("indent", Integer.toString(tag.getIndent())); layout.addAttribute("leading", Integer.toString(tag.getLeading())); } } private static void writeDefineFont(Element parentElement, DefineFont tag) { Element element = parentElement.addElement("definefont"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); Element glyphShapeTableElement = element.addElement("glyphshapetable"); Shape[] glyphShapeTable = tag.getGlyphShapeTable(); for (int i = 0; i < glyphShapeTable.length; i++) { RecordXMLWriter.writeShape(glyphShapeTableElement, glyphShapeTable[i]); } } private static void writeDefineFont2(Element parentElement, DefineFont2 tag) { Element element = parentElement.addElement("definefont2"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addAttribute("fontname", tag.getFontName()); if (tag.isANSI()) { element.addAttribute("ansi", "true"); } else if (tag.isShiftJIS()) { element.addAttribute("shiftjis", "true"); } if (tag.isBold()) { element.addAttribute("bold", "true"); } if (tag.isItalic()) { element.addAttribute("italic", "true"); } if (tag.isSmallText()) { element.addAttribute("smalltext", "true"); } writeLanguage(element, tag.getLanguageCode()); Shape[] table = tag.getGlyphShapeTable(); if (table != null) { Element glyphShapeTableElement = element.addElement("glyphshapetable"); char[] codeTable = tag.getCodeTable(); for (int i = 0; i < table.length; i++) { Element glyphElement = glyphShapeTableElement.addElement("glyph"); glyphElement.addAttribute("char", Character.toString(codeTable[i])); RecordXMLWriter.writeShape(glyphElement, table[i]); if (tag.hasLayout()) { glyphElement.addAttribute( "advance", Short.toString(tag.getAdvanceTable()[i])); RecordXMLWriter.writeRect( glyphElement, "bounds", tag.getBoundsTable()[i]); } } } if (tag.hasLayout()) { Element layout = element.addElement("layout"); layout.addAttribute("ascent", Integer.toString(tag.getAscent())); layout.addAttribute("descent", Integer.toString(tag.getDescent())); layout.addAttribute("leading", Integer.toString(tag.getLeading())); KerningRecord[] kerningTable = tag.getKerningTable(); if ((kerningTable != null) && (kerningTable.length > 0)) { Element kerningTableElement = layout.addElement("kerningtable"); for (int i = 0; i < kerningTable.length; i++) { KerningRecord record = kerningTable[i]; Element recordElement = kerningTableElement.addElement( "kerningrecord"); recordElement.addAttribute( "left", Character.toString(record.getLeft())); recordElement.addAttribute( "right", Character.toString(record.getRight())); recordElement.addAttribute( "adjust", Short.toString(record.getAdjustment())); } } } } private static void writeDefineFont3(Element parentElement, DefineFont3 tag) { Element element = parentElement.addElement("definefont3"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addAttribute("fontname", tag.getFontName()); if (tag.isBold()) { element.addAttribute("bold", "true"); } if (tag.isItalic()) { element.addAttribute("italic", "true"); } if (tag.isSmallText()) { element.addAttribute("smalltext", "true"); } writeLanguage(element, tag.getLanguageCode()); Shape[] table = tag.getGlyphShapeTable(); if (table != null) { Element glyphShapeTableElement = element.addElement("glyphshapetable"); char[] codeTable = tag.getCodeTable(); for (int i = 0; i < table.length; i++) { Element glyphElement = glyphShapeTableElement.addElement("glyph"); glyphElement.addAttribute("char", Character.toString(codeTable[i])); RecordXMLWriter.writeShape(glyphElement, table[i]); if (tag.hasLayout()) { glyphElement.addAttribute( "advance", Short.toString(tag.getAdvanceTable()[i])); RecordXMLWriter.writeRect( glyphElement, "bounds", tag.getBoundsTable()[i]); } } } if (tag.hasLayout()) { Element layout = element.addElement("layout"); layout.addAttribute("ascent", Integer.toString(tag.getAscent())); layout.addAttribute("descent", Integer.toString(tag.getDescent())); layout.addAttribute("leading", Integer.toString(tag.getLeading())); KerningRecord[] kerningTable = tag.getKerningTable(); if ((kerningTable != null) && (kerningTable.length > 0)) { Element kerningTableElement = layout.addElement("kerningtable"); for (int i = 0; i < kerningTable.length; i++) { KerningRecord record = kerningTable[i]; Element recordElement = kerningTableElement.addElement( "kerningrecord"); recordElement.addAttribute( "left", Character.toString(record.getLeft())); recordElement.addAttribute( "right", Character.toString(record.getRight())); recordElement.addAttribute( "adjust", Short.toString(record.getAdjustment())); } } } } private static void writeDefineFontAlignment( Element parentElement, DefineFontAlignment tag) { Element element = parentElement.addElement("definefontalignment"); element.addAttribute("fontid", Integer.toString(tag.getFontId())); switch (tag.getThickness()) { case DefineFontAlignment.THIN: element.addAttribute("thickness", "thin"); break; case DefineFontAlignment.MEDIUM: element.addAttribute("thickness", "medium"); break; case DefineFontAlignment.THICK: element.addAttribute("thickness", "thick"); break; } RecordXMLWriter.writeAlignmentZones(element, tag.getAlignmentZones()); } private static void writeDefineFontInfo( Element parentElement, DefineFontInfo tag) { Element element = parentElement.addElement("definefontinfo"); element.addAttribute("fontid", Integer.toString(tag.getFontId())); element.addAttribute("fontname", tag.getFontName()); if (tag.isANSI()) { element.addAttribute("ansi", "true"); } else if (tag.isShiftJIS()) { element.addAttribute("shiftjis", "true"); } if (tag.isBold()) { element.addAttribute("bold", "true"); } if (tag.isItalic()) { element.addAttribute("italic", "true"); } if (tag.isSmallText()) { element.addAttribute("smalltext", "true"); } char[] codeTable = tag.getCodeTable(); for (int i = 0; i < codeTable.length; i++) { element.addElement("char").addText(Character.toString(codeTable[i])); } } private static void writeDefineFontInfo2( Element parentElement, DefineFontInfo2 tag) { Element element = parentElement.addElement("definefontinfo2"); element.addAttribute("fontid", Integer.toString(tag.getFontId())); element.addAttribute("fontname", tag.getFontName()); if (tag.isBold()) { element.addAttribute("bold", "true"); } if (tag.isItalic()) { element.addAttribute("italic", "true"); } if (tag.isSmallText()) { element.addAttribute("smalltext", "true"); } writeLanguage(element, tag.getLangCode()); char[] codeTable = tag.getCodeTable(); for (int i = 0; i < codeTable.length; i++) { element.addElement("char").addText(Character.toString(codeTable[i])); } } private static void writeDefineMorphShape( Element parentElement, DefineMorphShape tag) { Element element = parentElement.addElement("definemorphshape"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); Shape startShape = tag.getStartShape(); Shape endShape = tag.getEndShape(); MorphLineStyles morphLineStyles = tag.getMorphLineStyles(); MorphFillStyles morphFillStyles = tag.getMorphFillStyles(); boolean zeroOffset = ((startShape == null) || (endShape == null) || (morphLineStyles == null) || (morphFillStyles == null)); Element startElement = element.addElement("start"); RecordXMLWriter.writeRect(startElement, "bounds", tag.getStartBounds()); Element endElement = element.addElement("end"); RecordXMLWriter.writeRect(endElement, "bounds", tag.getEndBounds()); if (!zeroOffset) { RecordXMLWriter.writeShape(startElement, startShape); RecordXMLWriter.writeShape(endElement, endShape); RecordXMLWriter.writeMorphLineStyles(element, morphLineStyles); RecordXMLWriter.writeMorphFillStyles(element, morphFillStyles); } } private static void writeDefineMorphShape2( Element parentElement, DefineMorphShape2 tag) { Element element = parentElement.addElement("definemorphshape2"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); Shape startShape = tag.getStartShape(); Shape endShape = tag.getEndShape(); MorphLineStyles morphLineStyles = tag.getMorphLineStyles(); MorphFillStyles morphFillStyles = tag.getMorphFillStyles(); boolean zeroOffset = ((startShape == null) || (endShape == null) || (morphLineStyles == null) || (morphFillStyles == null)); Element startElement = element.addElement("start"); RecordXMLWriter.writeRect( startElement, "shapebounds", tag.getStartShapeBounds()); RecordXMLWriter.writeRect( startElement, "edgebounds", tag.getStartEdgeBounds()); Element endElement = element.addElement("end"); RecordXMLWriter.writeRect( endElement, "shapebounds", tag.getEndShapeBounds()); RecordXMLWriter.writeRect(endElement, "edgebounds", tag.getEndEdgeBounds()); if (!zeroOffset) { RecordXMLWriter.writeShape(startElement, startShape); RecordXMLWriter.writeShape(endElement, endShape); RecordXMLWriter.writeMorphLineStyles(element, morphLineStyles); RecordXMLWriter.writeMorphFillStyles(element, morphFillStyles); } } private static void writeDefineShape(Element parentElement, DefineShape tag) { Element element = parentElement.addElement("defineshape"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeRect(element, "bounds", tag.getShapeBounds()); RecordXMLWriter.writeShapeWithStyle(element, tag.getShapes()); } private static void writeDefineShape2( Element parentElement, DefineShape2 tag) { Element element = parentElement.addElement("defineshape2"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeRect(element, "bounds", tag.getShapeBounds()); RecordXMLWriter.writeShapeWithStyle(element, tag.getShapes()); } private static void writeDefineShape3( Element parentElement, DefineShape3 tag) { Element element = parentElement.addElement("defineshape3"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeRect(element, "bounds", tag.getShapeBounds()); RecordXMLWriter.writeShapeWithStyle(element, tag.getShapes()); } private static void writeDefineShape4( Element parentElement, DefineShape4 tag) { Element element = parentElement.addElement("defineshape4"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeRect(element, "shapebounds", tag.getShapeBounds()); RecordXMLWriter.writeRect(element, "edgebounds", tag.getEdgeBounds()); RecordXMLWriter.writeShapeWithStyle(element, tag.getShapes()); } private static void writeDefineSound(Element parentElement, DefineSound tag) { Element element = parentElement.addElement("definesound"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addAttribute("format", getSoundFormatString(tag.getFormat())); element.addAttribute("rate", getSoundRateString(tag.getRate())); if (tag.is16BitSample()) { element.addAttribute("sample16bit", "true"); } if (tag.isStereo()) { element.addAttribute("stereo", "true"); } element.addAttribute("samplecount", Long.toString(tag.getSampleCount())); element.addText(Base64.encode(tag.getSoundData())); } private static void writeDefineSprite( Element parentElement, DefineSprite tag) { Element element = parentElement.addElement("definesprite"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); for (Iterator it = tag.getControlTags().iterator(); it.hasNext();) { Tag controlTag = (Tag) it.next(); writeTag(element, controlTag); } } private static void writeDefineText(Element parentElement, DefineText tag) { Element element = parentElement.addElement("definetext"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeRect(element, "bounds", tag.getTextBounds()); RecordXMLWriter.writeMatrix(element, "matrix", tag.getTextMatrix()); Element textRecordsElement = element.addElement("textrecords"); TextRecord[] textRecords = tag.getTextRecords(); for (int i = 0; i < textRecords.length; i++) { RecordXMLWriter.writeTextRecord(textRecordsElement, textRecords[i]); } } private static void writeDefineText2(Element parentElement, DefineText2 tag) { Element element = parentElement.addElement("definetext2"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeRect(element, "bounds", tag.getTextBounds()); RecordXMLWriter.writeMatrix(element, "matrix", tag.getTextMatrix()); Element textRecordsElement = element.addElement("textrecords"); TextRecord[] textRecords = tag.getTextRecords(); for (int i = 0; i < textRecords.length; i++) { RecordXMLWriter.writeTextRecord(textRecordsElement, textRecords[i]); } } private static void writeDefineVideoStream( Element parentElement, DefineVideoStream tag) { Element element = parentElement.addElement("definevideostream"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addAttribute("numframes", Integer.toString(tag.getNumFrames())); element.addAttribute("width", Integer.toString(tag.getWidth())); element.addAttribute("height", Integer.toString(tag.getHeight())); switch (tag.getDeblocking()) { case DefineVideoStream.DEBLOCKING_OFF: element.addAttribute("deblocking", "off"); break; case DefineVideoStream.DEBLOCKING_ON: element.addAttribute("deblocking", "on"); break; case DefineVideoStream.DEBLOCKING_PACKET: element.addAttribute("deblocking", "packet"); break; default: throw new IllegalArgumentException( "Illegal video deblocking setting: " + tag.getDeblocking()); } if (tag.isSmoothing()) { element.addAttribute("smoothing", "true"); } switch (tag.getCodecId()) { case DefineVideoStream.CODEC_SCREEN_VIDEO: element.addAttribute("codec", "screenvideo"); break; case DefineVideoStream.CODEC_SORENSON_H263: element.addAttribute("codec", "h263"); break; case DefineVideoStream.CODEC_VP6: element.addAttribute("codec", "vp6"); break; case DefineVideoStream.CODEC_VP6_ALPHA: element.addAttribute("codec", "vp6alpha"); break; case DefineVideoStream.CODEC_SCREEN_VIDEO_V2: element.addAttribute("codec", "screenvideov2"); break; case DefineVideoStream.CODEC_UNDEFINED: element.addAttribute("codec", "undefined"); break; default: throw new IllegalArgumentException( "Illegal video codec ID: " + tag.getCodecId()); } } private static void writeDoAction(Element parentElement, DoAction tag) { Element element = parentElement.addElement("doaction"); RecordXMLWriter.writeActionBlock(element, tag.getActions()); } private static void writeDoInitAction( Element parentElement, DoInitAction tag) { Element element = parentElement.addElement("doinitaction"); element.addAttribute("spriteid", Integer.toString(tag.getSpriteId())); RecordXMLWriter.writeActionBlock(element, tag.getInitActions()); } private static void writeEnableDebugger( Element parentElement, EnableDebugger tag) { Element element = parentElement.addElement("enabledebugger"); String password = tag.getPassword(); if (password != null) { element.addAttribute("password", password); } } private static void writeEnableDebugger2( Element parentElement, EnableDebugger2 tag) { Element element = parentElement.addElement("enabledebugger2"); String password = tag.getPassword(); if (password != null) { element.addAttribute("password", password); } } private static void writeExportAssets( Element parentElement, ExportAssets tag) { Element element = parentElement.addElement( "exportassets"); ExportAssets.ExportMapping[] mappings = tag.getExportMappings(); for (int i = 0; i < mappings.length; i++) { ExportAssets.ExportMapping mapping = mappings[i]; Element mappingElement = element.addElement("exportmapping"); mappingElement.addAttribute( "charid", Integer.toString(mapping.getCharacterId())); mappingElement.addAttribute("name", mapping.getName()); } } private static void writeFlashTypeSettings( Element parentElement, FlashTypeSettings tag) { Element element = parentElement.addElement("flashtypesettings"); element.addAttribute("textid", Integer.toString(tag.getTextId())); element.addAttribute("flashtype", Boolean.toString(tag.isFlashType())); switch (tag.getGridFit()) { case FlashTypeSettings.GRID_FIT_NONE: element.addAttribute("gridfit", "none"); break; case FlashTypeSettings.GRID_FIT_PIXEL: element.addAttribute("gridfit", "pixel"); break; case FlashTypeSettings.GRID_FIT_SUBPIXEL: element.addAttribute("gridfit", "subpixel"); break; } element.addAttribute( "thickness", StringUtilities.doubleToString(tag.getThickness())); element.addAttribute( "sharpness", StringUtilities.doubleToString(tag.getSharpness())); } private static void writeFrameLabel(Element parentElement, FrameLabel tag) { Element element = parentElement.addElement("framelabel"); element.addAttribute("name", tag.getName()); if (tag.isNamedAnchor()) { element.addAttribute("namedanchor", "true"); } } private static void writeFreeCharacter( Element parentElement, FreeCharacter tag) { Element element = parentElement.addElement("freecharacter"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); } private static void writeImportAssets( Element parentElement, ImportAssets tag) { Element element = parentElement.addElement("importassets"); element.addAttribute("url", tag.getUrl()); ImportAssets.ImportMapping[] mappings = tag.getImportMappings(); for (int i = 0; i < mappings.length; i++) { ImportAssets.ImportMapping mapping = mappings[i]; Element mappingElement = element.addElement("importmapping"); mappingElement.addAttribute("name", mapping.getName()); mappingElement.addAttribute( "charid", Integer.toString(mapping.getCharacterId())); } } private static void writeImportAssets2( Element parentElement, ImportAssets2 tag) { Element element = parentElement.addElement("importassets2"); element.addAttribute("url", tag.getUrl()); ImportAssets.ImportMapping[] mappings = tag.getImportMappings(); for (int i = 0; i < mappings.length; i++) { ImportAssets.ImportMapping mapping = mappings[i]; Element mappingElement = element.addElement("importmapping"); mappingElement.addAttribute("name", mapping.getName()); mappingElement.addAttribute( "charid", Integer.toString(mapping.getCharacterId())); } } private static void writeJPEGTables(Element parentElement, JPEGTables tag) { Element element = parentElement.addElement("jpegtables"); element.addElement("jpegdata").addText(Base64.encode(tag.getJpegData())); } private static void writeLanguage(Element parentElement, LangCode langCode) { if (langCode != null) { switch (langCode.getLanguageCode()) { case LangCode.LATIN: parentElement.addAttribute("language", "latin"); break; case LangCode.UNDEFINED: parentElement.addAttribute("language", "undefined"); break; case LangCode.JAPANESE: parentElement.addAttribute("language", "japanese"); break; case LangCode.KOREAN: parentElement.addAttribute("language", "korean"); break; case LangCode.SIMPLIFIED_CHINESE: parentElement.addAttribute("language", "simpchinese"); break; case LangCode.TRADITIONAL_CHINESE: parentElement.addAttribute("language", "tradchinese"); break; default: throw new IllegalArgumentException( "Illegal language code: " + langCode.getLanguageCode()); } } } private static void writeMalformedTag( Element parentElement, MalformedTag tag) { Element element = parentElement.addElement("malformedtag"); element.addAttribute("code", Integer.toString(tag.getCode())); Exception exception = tag.getException(); Element exceptionElement = element.addElement("exception"); exceptionElement.addAttribute("class", exception.getClass().getName()); exceptionElement.addAttribute("message", exception.toString()); element.addElement("data").addText(Base64.encode(tag.getData())); } private static void writePlaceObject(Element parentElement, PlaceObject tag) { Element element = parentElement.addElement("placeobject"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addAttribute("depth", Integer.toString(tag.getDepth())); RecordXMLWriter.writeMatrix(element, tag.getMatrix()); CXform colorTransform = tag.getColorTransform(); if (colorTransform != null) { RecordXMLWriter.writeCXForm(element, colorTransform); } } private static void writePlaceObject2( Element parentElement, PlaceObject2 tag) { Element element = parentElement.addElement("placeobject2"); element.addAttribute("depth", Integer.toString(tag.getDepth())); if (tag.hasCharacter()) { element.addAttribute("charid", Integer.toString(tag.getCharacterId())); } if (tag.hasName()) { element.addAttribute("name", tag.getName()); } if (tag.isMove()) { element.addAttribute("move", "true"); } if (tag.hasMatrix()) { RecordXMLWriter.writeMatrix(element, tag.getMatrix()); } if (tag.hasColorTransform()) { RecordXMLWriter.writeCXFormWithAlpha(element, tag.getColorTransform()); } if (tag.hasRatio()) { element.addAttribute("ratio", Integer.toString(tag.getRatio())); } if (tag.hasClipDepth()) { element.addAttribute("clipdepth", Integer.toString(tag.getClipDepth())); } if (tag.hasClipActions()) { RecordXMLWriter.writeClipActions(element, tag.getClipActions()); } } private static void writePlaceObject3( Element parentElement, PlaceObject3 tag) { Element element = parentElement.addElement("placeobject3"); element.addAttribute("depth", Integer.toString(tag.getDepth())); if (tag.hasCharacter()) { element.addAttribute("charid", Integer.toString(tag.getCharacterId())); } if (tag.hasName()) { element.addAttribute("name", tag.getName()); } if (tag.isMove()) { element.addAttribute("move", "true"); } if (tag.hasMatrix()) { RecordXMLWriter.writeMatrix(element, tag.getMatrix()); } if (tag.hasColorTransform()) { RecordXMLWriter.writeCXFormWithAlpha(element, tag.getColorTransform()); } if (tag.hasRatio()) { element.addAttribute("ratio", Integer.toString(tag.getRatio())); } if (tag.hasClipDepth()) { element.addAttribute("clipdepth", Integer.toString(tag.getClipDepth())); } if (tag.hasClipActions()) { RecordXMLWriter.writeClipActions(element, tag.getClipActions()); } if (tag.hasBlendMode()) { element.addAttribute( "blendmode", BlendMode.getDescription(tag.getBlendMode())); } if (tag.isCacheAsBitmap()) { element.addAttribute("cacheasbitmap", "true"); } if (tag.hasFilters()) { RecordXMLWriter.writeFilters(element, tag.getFilters()); } } private static void writeProtect(Element parentElement, Protect tag) { Element element = parentElement.addElement("protect"); String password = tag.getPassword(); if (password != null) { element.addElement("password", tag.getPassword()); } } private static void writeRemoveObject( Element parentElement, RemoveObject tag) { Element element = parentElement.addElement("removeobject"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); element.addAttribute("depth", Integer.toString(tag.getDepth())); } private static void writeRemoveObject2( Element parentElement, RemoveObject2 tag) { Element element = parentElement.addElement("removeobject2"); element.addAttribute("depth", Integer.toString(tag.getDepth())); } private static void writeScale9Grid(Element parentElement, Scale9Grid tag) { Element element = parentElement.addElement("scale9grid"); element.addAttribute("charid", Integer.toString(tag.getCharacterId())); RecordXMLWriter.writeRect(element, "grid", tag.getGrid()); } private static void writeScriptLimits( Element parentElement, ScriptLimits tag) { Element element = parentElement.addElement("scriptlimits"); element.addAttribute( "maxrecursiondepth", Integer.toString(tag.getMaxRecursionDepth())); element.addAttribute( "scripttimeout", Integer.toString(tag.getScriptTimeoutSeconds())); } private static void writeSetTabIndex(Element parentElement, SetTabIndex tag) { Element element = parentElement.addElement("settabindex"); element.addAttribute("depth", Integer.toString(tag.getDepth())); element.addAttribute("tabindex", Integer.toString(tag.getTabIndex())); } private static void writeShowFrame(Element parentElement, ShowFrame tag) { parentElement.addElement("showframe"); } private static void writeSoundStreamBlock( Element parentElement, SoundStreamBlock tag) { Element element = parentElement.addElement("soundstreamblock"); element.addElement("streamsounddata").addText( Base64.encode(tag.getStreamSoundData())); } private static void writeSoundStreamHead( Element parentElement, SoundStreamHead tag) { Element element = parentElement.addElement("soundstreamhead"); element.addAttribute( "streamformat", getSoundFormatString(tag.getStreamFormat())); element.addAttribute("streamrate", getSoundRateString(tag.getStreamRate())); if (tag.isStreamStereo()) { element.addAttribute("streamstereo", "true"); } element.addAttribute( "streamsamplecount", Integer.toString(tag.getStreamSampleCount())); element.addAttribute( "playbackrate", getSoundRateString(tag.getPlaybackRate())); if (tag.isPlaybackStereo()) { element.addAttribute("playbackstereo", "true"); } if (tag.getStreamFormat() == SoundStreamHead.FORMAT_MP3) { element.addAttribute("latencyseek", Short.toString(tag.getLatencySeek())); } } private static void writeSoundStreamHead2( Element parentElement, SoundStreamHead2 tag) { Element element = parentElement.addElement("soundstreamhead2"); element.addAttribute( "streamformat", getSoundFormatString(tag.getStreamFormat())); element.addAttribute("streamrate", getSoundRateString(tag.getStreamRate())); if (tag.isStream16BitSample()) { element.addAttribute("streamsample16bit", "true"); } if (tag.isStreamStereo()) { element.addAttribute("streamstereo", "true"); } element.addAttribute( "streamsamplecount", Integer.toString(tag.getStreamSampleCount())); element.addAttribute( "playbackrate", getSoundRateString(tag.getPlaybackRate())); if (tag.isPlayback16BitSample()) { element.addAttribute("playbacksample16bit", "true"); } if (tag.isPlaybackStereo()) { element.addAttribute("playbackstereo", "true"); } if (tag.getStreamFormat() == SoundStreamHead.FORMAT_MP3) { element.addAttribute("latencyseek", Short.toString(tag.getLatencySeek())); } } private static void writeStartSound(Element parentElement, StartSound tag) { Element element = parentElement.addElement("startsound"); element.addAttribute("soundid", Integer.toString(tag.getSoundId())); RecordXMLWriter.writeSoundInfo(element, tag.getSoundInfo()); } private static void writeUnknownTag(Element parentElement, UnknownTag tag) { Element element = parentElement.addElement("unknowntag"); element.addAttribute("code", Integer.toString(tag.getCode())); element.addText(Base64.encode(tag.getData())); } private static void writeVideoFrame(Element parentElement, VideoFrame tag) { Element element = parentElement.addElement("videoframe"); element.addAttribute("streamid", Integer.toString(tag.getStreamId())); element.addAttribute("framenum", Integer.toString(tag.getFrameNum())); element.addElement("videodata").addText(Base64.encode(tag.getVideoData())); } }