Exemple #1
0
        private void ReadFontAlignZones()
        {
            SWFFont font = fontDict[this.sdtr.ReadUI16()];

            if (font == null)
            {
                throw new SWFModellerException(SWFModellerError.SWFParsing, "Bad font ID in pixel alignment data", swf.Context);
            }

            font.ThicknessHint = (SWFFont.Thickness) this.sdtr.ReadUBits(2);
            /*(void)*/ this.sdtr.ReadUBits(6); /* Reserved */

            char[] codes = font.CodePoints;
            for (int i = 0; i < codes.Length; i++)
            {
                PixelAlignment alignment = new PixelAlignment();

                alignment.ZoneInfo = new PixelAlignment.ZoneData[this.sdtr.ReadUI8()];
                for (int j = 0; j < alignment.ZoneInfo.Length; j++)
                {
                    alignment.ZoneInfo[j] = new PixelAlignment.ZoneData()
                    {
                        AlignmentCoord = this.sdtr.ReadUI16(),
                        Range          = this.sdtr.ReadUI16()
                    };
                }

                /*(void)*/ this.sdtr.ReadUBits(6); /* Reserved */

                alignment.HasY = this.sdtr.ReadBit();
                alignment.HasX = this.sdtr.ReadBit();

                font.AddPixelAlignment(codes[i], alignment);
            }
        }
Exemple #2
0
        private void ReadFontName()
        {
            SWFFont font = fontDict[this.sdtr.ReadUI16()];

            if (font == null)
            {
                throw new SWFModellerException(SWFModellerError.SWFParsing, "Bad font ID in font name data", swf.Context);
            }

            font.FullName  = this.sdtr.ReadString();
            font.Copyright = this.sdtr.ReadString();
        }
Exemple #3
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();
            }
        }
Exemple #4
0
        private void ReadFont(Tag fontType)
        {
            int fontID = this.sdtr.ReadUI16();

            /* Bunch of flags */
            bool hasLayout     = this.sdtr.ReadBit();
            bool isShiftJIS    = this.sdtr.ReadBit();
            bool isSmallText   = this.sdtr.ReadBit();
            bool isANSI        = this.sdtr.ReadBit();
            bool isWideOffsets = this.sdtr.ReadBit();
            bool isWideCodes   = this.sdtr.ReadBit();
            bool isItalic      = this.sdtr.ReadBit();
            bool isBold        = this.sdtr.ReadBit();

            if (!isWideCodes)
            {
                throw new SWFModellerException(SWFModellerError.SWFParsing,
                                               "Non-wide codes in font encodings are not valid.", swf.Context);
            }

            if (isShiftJIS)
            {
                /* ISSUE 50 */
                throw new SWFModellerException(SWFModellerError.UnimplementedFeature,
                                               "ShiftJIS character encoding is not supported.", swf.Context);
            }

            int    language  = this.sdtr.ReadUI8();
            string name      = this.sdtr.ReadLengthedUTF8(this.sdtr.ReadUI8());
            int    numGlyphs = this.sdtr.ReadUI16();

#if DEBUG
            this.Log("id=" + fontID + ", name=" + name);
#endif

            SWFFont font = new SWFFont(
                (SWFFont.Language)language,
                name,
                isBold,
                isItalic,
                isSmallText,
                numGlyphs);

            int startOffset = (int)this.sdtr.Offset; /* The offset table measures from this point. */

            int[] shapeOffsets = new int[numGlyphs];
            for (int i = 0; i < numGlyphs; i++)
            {
                shapeOffsets[i] = isWideOffsets ? (int)this.sdtr.ReadUI32() : this.sdtr.ReadUI16();
            }

            int codeTableOffset = isWideOffsets ? (int)this.sdtr.ReadUI32() : this.sdtr.ReadUI16();

            IShape[] shapes = new IShape[numGlyphs];

            for (int i = 0; i < numGlyphs; i++)
            {
                int shapeOffset = (int)sdtr.Offset - startOffset;
                if (shapeOffsets[i] != shapeOffset)
                {
                    throw new SWFModellerException(SWFModellerError.SWFParsing, "Bad font data.", swf.Context);
                }

                int end = codeTableOffset;
                if (i < numGlyphs - 1)
                {
                    end = shapeOffsets[i + 1];
                }

                int len = end - shapeOffset;

                byte[] shapeData = this.sdtr.ReadByteBlock(len);

                shapes[i] = new ShapeParser().Parse(fontType, shapeData, this);
            }

            char[] codes = new char[numGlyphs];

            for (int i = 0; i < numGlyphs; i++)
            {
                codes[i] = (char)this.sdtr.ReadUI16();
                font.AddGlyph(codes[i], shapes[i]);
            }


            if (hasLayout)
            {
                font.Ascent  = this.sdtr.ReadSI16();
                font.Descent = this.sdtr.ReadSI16();
                font.Leading = this.sdtr.ReadSI16();

                GlyphLayout[] layouts = new GlyphLayout[numGlyphs];

                for (int i = 0; i < numGlyphs; i++)
                {
                    layouts[i] = new GlyphLayout()
                    {
                        Advance = this.sdtr.ReadSI16()
                    };
                }

                for (int i = 0; i < numGlyphs; i++)
                {
                    layouts[i].Bounds = this.sdtr.ReadRect();
                    font.AddLayout(codes[i], layouts[i]);
                }

                int           kerningCount = this.sdtr.ReadUI16();
                KerningPair[] kernTable    = new KerningPair[kerningCount];

                for (int i = 0; i < kerningCount; i++)
                {
                    kernTable[i] = new KerningPair()
                    {
                        LeftChar   = (char)(isWideCodes ? this.sdtr.ReadUI16() : this.sdtr.ReadUI8()),
                        RightChar  = (char)(isWideCodes ? this.sdtr.ReadUI16() : this.sdtr.ReadUI8()),
                        Adjustment = this.sdtr.ReadSI16()
                    };
                }

                font.KerningTable = kernTable;
            }

            fontDict.Add(fontID, font);
            swf.AddFont(font);
        }
Exemple #5
0
 /// <summary>
 /// Adds a font to the SWF.
 /// </summary>
 /// <param name="font">The font.</param>
 internal void AddFont(SWFFont font)
 {
     this.fonts.Add(font);
 }