Beispiel #1
0
        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();
            }
        }
        /// <summary>
        /// Writes a rectangle to the stream
        /// </summary>
        /// <remarks>WARNING: Bear in mind that the writer will probably not be
        /// byte-aligned after calling this.</remarks>
        /// <param name="r">The rectangle to write.</param>
        public void WriteRect(Rect r)
        {
            int xmin = (int)(r.XMin * SWFValues.TwipsFactor);
            int xmax = (int)(r.XMax * SWFValues.TwipsFactor);
            int ymin = (int)(r.YMin * SWFValues.TwipsFactor);
            int ymax = (int)(r.YMax * SWFValues.TwipsFactor);

            int nbits = Math.Max(RequiredBits(xmin),
                    Math.Max(RequiredBits(xmax),
                            Math.Max(RequiredBits(ymin), RequiredBits(ymax))));

            this.WriteUBits((uint)nbits, 5);

            this.WriteSBits(xmin, nbits);
            this.WriteSBits(xmax, nbits);
            this.WriteSBits(ymin, nbits);
            this.WriteSBits(ymax, nbits);
        }
Beispiel #3
0
        private void ReadHeader(SWFContext ctx)
        {
            int sig = this.sdtr.ReadUI24();
            if (sig != SIG_COMPRESSED && sig != SIG_UNCOMPRESSED)
            {
                throw new SWFModellerException(
                        SWFModellerError.SWFParsing,
                        @"Not a SWF file", ctx);
            }

            bool compressed = sig == SIG_COMPRESSED;

            this.version = this.sdtr.ReadUI8();
            if (this.version < 9)
            {
                throw new SWFModellerException(
                        SWFModellerError.SWFParsing,
                        @"Only SWF 9+ is supported (Found " + this.version +")", ctx);
            }
            #if DEBUG
            this.Log("SWF version = " + this.version);
            #endif
            this.fileLen = this.sdtr.ReadUI32();

            if (compressed)
            {
                this.sdtr.SwitchToDeflateMode(this.fileLen);
            }

            this.frameSize = this.sdtr.ReadRect();

            this.fps = this.sdtr.ReadFIXED8();

            this.frameCount = this.sdtr.ReadUI16();
        }