private void WriteFileAttributesTag() { WriteBuffer tagWriter = this.OpenTag(Tag.FileAttributes); /* ISSUE 27: Some of these flags are for SWF v10 - check the flash 9 spec for defaults instead. */ /* No data written yet, so data will be aligned. */ tagWriter.WriteBit(false); /* Reserved, must be 0 */ tagWriter.WriteBit(true); /* UseDirectBlit, TODO: We set this to '1' but I dunno what the IDE does. */ tagWriter.WriteBit(true); /* UseGPU, TODO: We set this to '1' but I dunno what the IDE does. */ tagWriter.WriteBit(this.options.RDFMetadata != null); tagWriter.WriteBit(true); /* AS3, because we don't like AS2. Boo. */ tagWriter.WriteUBits(0, 2); /* Reserved, must be 0 */ tagWriter.WriteBit(false); /* UseNetwork. TODO: Check what the IDE sets for this. */ tagWriter.WriteUBits(0, 24); /* Reserved, must be 0 */ this.CloseTag(); if (this.options.RDFMetadata != null) { this.OpenTag(Tag.Metadata) .WriteString(this.options.RDFMetadata); this.CloseTag(); } }
private void WriteFont(SWFFont font, int fid) { WriteBuffer fontTag = this.OpenTag(Tag.DefineFont3, font.Name + "; id=" + fid); char[] codes = font.CodePoints; /* Tag.DefineFont3 */ { fontTag.WriteUI16((uint)fid); fontTag.WriteBit(font.HasLayout); fontTag.WriteBit(false); /* ISSUE 50: ShiftJIS support */ fontTag.WriteBit(font.IsSmall); fontTag.WriteBit(false); /* ISSUE 51: ANSI support, though I think this might never be false. */ fontTag.WriteBit(true); /* ISSUE 52: We always write wide offsets. This is because we're too lazy to measure our table. */ fontTag.WriteBit(true); /* Spec says must be true. */ fontTag.WriteBit(font.IsItalic); fontTag.WriteBit(font.IsBold); fontTag.WriteUI8((uint)font.LanguageCode); fontTag.WriteString(font.Name, true); fontTag.WriteUI16((uint)font.GlyphCount); byte[][] shapeData = new byte[font.GlyphCount][]; int totalShapeBytes = 0; for (int i = 0; i < font.GlyphCount; i++) { Tag format; shapeData[i] = ShapeWriter.ShapeToBytes(font.GetGlyphShape(codes[i]), out format); if (format != Tag.DefineFont3) { throw new SWFModellerException(SWFModellerError.Internal, "Can't write non-font shapes as glyphs"); } totalShapeBytes += shapeData[i].Length; } int startOffset = font.GlyphCount * 4 + 4; /* 4 bytes per offset (wide offsets) + 4 for the code table offset */ int nextOffset = startOffset; foreach (byte[] shapeBytes in shapeData) { fontTag.WriteUI32((uint)nextOffset); nextOffset += shapeBytes.Length; } fontTag.WriteUI32((uint)(startOffset + totalShapeBytes)); foreach (byte[] shapeBytes in shapeData) { fontTag.WriteBytes(shapeBytes); } foreach (char code in codes) { fontTag.WriteUI16((uint)code); } if (font.HasLayout) { fontTag.WriteSI16(font.Ascent.Value); fontTag.WriteSI16(font.Descent.Value); fontTag.WriteSI16(font.Leading.Value); Rect[] bounds = new Rect[font.GlyphCount]; int boundsPos = 0; foreach (char c in codes) { GlyphLayout gl = font.GetLayout(c); fontTag.WriteSI16(gl.Advance); bounds[boundsPos++] = gl.Bounds; } foreach (Rect bound in bounds) { fontTag.WriteRect(bound); fontTag.Align8(); } fontTag.WriteUI16((uint)font.KerningTable.Length); foreach (KerningPair kern in font.KerningTable) { fontTag.WriteUI16(kern.LeftChar); fontTag.WriteUI16(kern.RightChar); fontTag.WriteSI16(kern.Adjustment); } } } this.CloseTag(); if (font.HasPixelAlignment) { WriteBuffer zonesTag = this.OpenTag(Tag.DefineFontAlignZones, font.Name + "; id=" + fid); zonesTag.WriteUI16((uint)fid); if (font.ThicknessHint == null) { throw new SWFModellerException(SWFModellerError.Internal, "Can't have pixel aligmnent without a font thickness hint."); } zonesTag.WriteUBits((uint)font.ThicknessHint, 2); zonesTag.WriteUBits(0, 6); /* Reserved */ foreach (char c in codes) { PixelAlignment pa = font.GetPixelAligment(c); if (pa.ZoneInfo.Length != 2) { throw new SWFModellerException(SWFModellerError.Internal, "Pixel aligment should always have 2 zones."); } zonesTag.WriteUI8((uint)pa.ZoneInfo.Length); foreach (PixelAlignment.ZoneData zi in pa.ZoneInfo) { /* These int values are just unparsed 16-bit floats. */ zonesTag.WriteUI16((uint)zi.AlignmentCoord); zonesTag.WriteUI16((uint)zi.Range); } zonesTag.WriteUBits(0, 6); /* Reserved */ zonesTag.WriteBit(pa.HasY); zonesTag.WriteBit(pa.HasX); } this.CloseTag(); } if (font.HasExtraNameInfo) { WriteBuffer nameTag = this.OpenTag(Tag.DefineFontName, font.FullName + "; id=" + fid); nameTag.WriteUI16((uint)fid); nameTag.WriteString(font.FullName); nameTag.WriteString(font.Copyright); this.CloseTag(); } }
/// <param name="fontID">Pass -1 if this has no font.</param> private void WriteEditText(EditText text, int fontID) { int cid = characterMarshal.GetIDFor(text); WriteBuffer textTag = this.OpenTag(Tag.DefineEditText, "; id=" + cid); /* Tag.DefineEditText */ { textTag.WriteUI16((uint)cid); textTag.WriteRect(text.Bounds); textTag.Align8(); textTag.WriteBit(text.HasText); textTag.WriteBit(text.WordWrapEnabled); textTag.WriteBit(text.IsMultiline); textTag.WriteBit(text.IsPassword); textTag.WriteBit(text.IsReadOnly); textTag.WriteBit(text.HasTextColor); textTag.WriteBit(text.HasMaxLength); textTag.WriteBit(text.HasFont); textTag.WriteBit(text.HasFontClass); textTag.WriteBit(text.IsAutoSized); textTag.WriteBit(text.HasLayout); textTag.WriteBit(text.IsNonSelectable); textTag.WriteBit(text.HasBorder); textTag.WriteBit(text.IsStatic); textTag.WriteBit(text.IsHTML); textTag.WriteBit(text.UseOutlines); if (text.HasFont) { textTag.WriteUI16((uint)fontID); } if (text.HasFontClass) { /* ISSUE 14 */ throw new SWFModellerException(SWFModellerError.UnimplementedFeature, "Font classes can't be written."); } if (text.HasFont) { textTag.WriteUI16((uint)text.FontHeight); } if (text.HasTextColor) { textTag.WriteRGBA(text.Color.ToArgb()); } if (text.HasMaxLength) { textTag.WriteUI16((uint)text.MaxLength.Value); } if (text.HasLayout) { EditText.Layout layout = text.LayoutInfo; textTag.WriteUI8((uint)layout.Align); textTag.WriteUI16((uint)layout.LeftMargin); textTag.WriteUI16((uint)layout.RightMargin); textTag.WriteUI16((uint)layout.Indent); textTag.WriteSI16(layout.Leading); } textTag.WriteString(text.VarName); if (text.HasText) { textTag.WriteString(text.Text); } } CloseTag(); }
private void WritePlaceObjectTag(PlaceObject po) { Tag placeTag = this.TagForPlaceObject(po); WriteBuffer tagWriter = this.OpenTag(placeTag); int cid; switch (placeTag) { case Tag.PlaceObject: if (!po.HasCharacter) { throw new SWFModellerException( SWFModellerError.Internal, "A PlaceObject display list item must have a character unless it is a move instruction."); } #if DEBUG if (!this.characterMarshal.HasMarshalled(po.Character)) { throw new SWFModellerException( SWFModellerError.Internal, "Can't place object that hasn't been written to stream yet."); } #endif cid = this.characterMarshal.GetIDFor(po.Character); tagWriter.WriteUI16((uint)cid); #if DEBUG this.LogMessage("po cid =" + cid); #endif tagWriter.WriteUI16((uint)po.LayerIndex); if (!po.HasMatrix) { throw new SWFModellerException( SWFModellerError.Internal, "A PlaceObject display list item must have a Matrix, unless it's a PlaceObject2 tag. See spec for info, I can't work it out."); } tagWriter.WriteMatrix(po.Matrix); if (po.HasColorTransform) { tagWriter.WriteColorTransform(po.CXForm, false); } break; case Tag.PlaceObject2: tagWriter.WriteBit(po.HasClipActions); tagWriter.WriteBit(po.HasClipDepth); tagWriter.WriteBit(po.HasName); tagWriter.WriteBit(po.HasRatio); tagWriter.WriteBit(po.HasColorTransform); tagWriter.WriteBit(po.HasMatrix); tagWriter.WriteBit(po.HasCharacter); tagWriter.WriteBit(po.IsMove); tagWriter.WriteUI16((uint)po.LayerIndex); if (po.HasCharacter) { #if DEBUG if (!this.characterMarshal.HasMarshalled(po.Character)) { throw new SWFModellerException( SWFModellerError.Internal, "Can't place object that hasn't been written to stream yet."); } #endif cid = this.characterMarshal.GetIDFor(po.Character); tagWriter.WriteUI16((uint)cid); #if DEBUG this.LogMessage("po cid =" + cid); #endif } if (po.HasMatrix) { tagWriter.WriteMatrix(po.Matrix); } if (po.HasColorTransform) { tagWriter.WriteColorTransform(po.CXForm, true); } if (po.HasRatio) { tagWriter.WriteUI16((uint)po.Ratio); } if (po.HasName) { #if DEBUG this.LogMessage("name=" + po.Name); #endif tagWriter.WriteString(po.Name); } if (po.HasClipDepth) { tagWriter.WriteUI16((uint)po.ClipDepth); } if (po.HasClipActions) { throw new SWFModellerException( SWFModellerError.Internal, "Clips cannot have actions in the target SWF version."); } break; default: /* ISSUE 73 */ throw new SWFModellerException( SWFModellerError.UnimplementedFeature, "Unsupported PlaceObject tag: " + placeTag.ToString()); } #if DEBUG this.LogMessage("po char =" + po.Character); #endif this.CloseTag(); }