internal bool CanMergeWith(SWFFont font) { if (!font.HasExtraNameInfo || !this.HasExtraNameInfo) { /* ISSUE 77 */ throw new SWFModellerException(SWFModellerError.UnimplementedFeature, "Fonts without full names cause us problems."); } return(this.FullName == font.FullName && this.IsBold == font.IsBold && this.IsItalic == font.IsItalic && this.IsSmall == font.IsSmall && this.HasLayout == font.HasLayout && this.HasPixelAlignment == font.HasPixelAlignment); }
internal bool CanMergeWith(SWFFont font) { if (!font.HasExtraNameInfo || !this.HasExtraNameInfo) { /* ISSUE 77 */ throw new SWFModellerException(SWFModellerError.UnimplementedFeature, "Fonts without full names cause us problems."); } return this.FullName == font.FullName && this.IsBold == font.IsBold && this.IsItalic == font.IsItalic && this.IsSmall == font.IsSmall && this.HasLayout == font.HasLayout && this.HasPixelAlignment == font.HasPixelAlignment; }
/// <summary> /// Adds a font to the SWF. /// </summary> /// <param name="font">The font.</param> internal void AddFont(SWFFont font) { this.fonts.Add(font); }
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(); } }
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); }