/** * This will parse the kern data. * * @param fontMetrics The metrics class to put the parsed data into. * * @throws IOException If there is an error parsing the data. */ private void ParseKernData(FontMetrics fontMetrics) { string nextCommand; while (!(nextCommand = ReadString()).Equals(END_KERN_DATA, StringComparison.Ordinal)) { switch (nextCommand) { case START_TRACK_KERN: int countTrackKern = ReadInt(); for (int i = 0; i < countTrackKern; i++) { TrackKern kern = new TrackKern(); kern.Degree = ReadInt(); kern.MinPointSize = Readfloat(); kern.MinKern = Readfloat(); kern.MaxPointSize = Readfloat(); kern.MaxKern = Readfloat(); fontMetrics.AddTrackKern(kern); } string endTrackKern = ReadString(); if (!endTrackKern.Equals(END_TRACK_KERN, StringComparison.Ordinal)) { throw new IOException("Error: Expected '" + END_TRACK_KERN + "' actual '" + endTrackKern + "'"); } break; case START_KERN_PAIRS: int countKernPairs = ReadInt(); for (int i = 0; i < countKernPairs; i++) { KernPair pair = ParseKernPair(); fontMetrics.AddKernPair(pair); } string endKernPairs = ReadString(); if (!endKernPairs.Equals(END_KERN_PAIRS, StringComparison.Ordinal)) { throw new IOException("Error: Expected '" + END_KERN_PAIRS + "' actual '" + endKernPairs + "'"); } break; case START_KERN_PAIRS0: int countKernPairs0 = ReadInt(); for (int i = 0; i < countKernPairs0; i++) { KernPair pair = ParseKernPair(); fontMetrics.AddKernPair0(pair); } string endKernPairs0 = ReadString(); if (!endKernPairs0.Equals(END_KERN_PAIRS, StringComparison.Ordinal)) { throw new IOException("Error: Expected '" + END_KERN_PAIRS + "' actual '" + endKernPairs0 + "'"); } break; case START_KERN_PAIRS1: int countKernPairs1 = ReadInt(); for (int i = 0; i < countKernPairs1; i++) { KernPair pair = ParseKernPair(); fontMetrics.AddKernPair1(pair); } string endKernPairs1 = ReadString(); if (!endKernPairs1.Equals(END_KERN_PAIRS, StringComparison.Ordinal)) { throw new IOException("Error: Expected '" + END_KERN_PAIRS + "' actual '" + endKernPairs1 + "'"); } break; default: throw new IOException("Unknown kerning data type '" + nextCommand + "'"); } } }
/** * This will parse a font metrics item. * * @return The parse font metrics item. * * @throws IOException If there is an error reading the AFM file. */ private FontMetrics ParseFontMetric(bool reducedDataset) { FontMetrics fontMetrics = new FontMetrics(); string startFontMetrics = ReadString(); if (!START_FONT_METRICS.Equals(startFontMetrics, StringComparison.Ordinal)) { throw new IOException("Error: The AFM file should start with " + START_FONT_METRICS + " and not '" + startFontMetrics + "'"); } fontMetrics.AFMVersion = Readfloat(); string nextCommand; bool charMetricsRead = false; while (!END_FONT_METRICS.Equals(nextCommand = ReadString(), StringComparison.Ordinal)) { switch (nextCommand) { case FONT_NAME: fontMetrics.FontName = ReadLine(); break; case FULL_NAME: fontMetrics.FullName = ReadLine(); break; case FAMILY_NAME: fontMetrics.FamilyName = ReadLine(); break; case WEIGHT: fontMetrics.Weight = ReadLine(); break; case FONT_BBOX: var bBox = new SKRect(); bBox.Left = Readfloat(); bBox.Bottom = Readfloat(); bBox.Right = Readfloat(); bBox.Top = Readfloat(); fontMetrics.FontBBox = bBox; break; case VERSION: fontMetrics.FontVersion = ReadLine(); break; case NOTICE: fontMetrics.Notice = ReadLine(); break; case ENCODING_SCHEME: fontMetrics.EncodingScheme = ReadLine(); break; case MAPPING_SCHEME: fontMetrics.MappingScheme = ReadInt(); break; case ESC_CHAR: fontMetrics.EscChar = ReadInt(); break; case CHARACTER_SET: fontMetrics.CharacterSet = ReadLine(); break; case CHARACTERS: fontMetrics.Characters = ReadInt(); break; case IS_BASE_FONT: fontMetrics.IsBaseFont = ReadBoolean(); break; case V_VECTOR: float[] vector = new float[2]; vector[0] = Readfloat(); vector[1] = Readfloat(); fontMetrics.VVector = vector; break; case IS_FIXED_V: fontMetrics.IsFixedV = ReadBoolean(); break; case CAP_HEIGHT: fontMetrics.CapHeight = Readfloat(); break; case X_HEIGHT: fontMetrics.XHeight = Readfloat(); break; case ASCENDER: fontMetrics.Ascender = Readfloat(); break; case DESCENDER: fontMetrics.Descender = Readfloat(); break; case STD_HW: fontMetrics.StandardHorizontalWidth = Readfloat(); break; case STD_VW: fontMetrics.StandardVerticalWidth = Readfloat(); break; case COMMENT: fontMetrics.AddComment(ReadLine()); break; case UNDERLINE_POSITION: fontMetrics.UnderlinePosition = Readfloat(); break; case UNDERLINE_THICKNESS: fontMetrics.UnderlineThickness = Readfloat(); break; case ITALIC_ANGLE: fontMetrics.ItalicAngle = Readfloat(); break; case CHAR_WIDTH: float[] widths = new float[2]; widths[0] = Readfloat(); widths[1] = Readfloat(); fontMetrics.CharWidth = widths; break; case IS_FIXED_PITCH: fontMetrics.IsFixedPitch = ReadBoolean(); break; case START_CHAR_METRICS: int countMetrics = ReadInt(); List <CharMetric> charMetrics = new List <CharMetric>(countMetrics); for (int i = 0; i < countMetrics; i++) { CharMetric charMetric = ParseCharMetric(); charMetrics.Add(charMetric); } string endCharMetrics = ReadString(); if (!endCharMetrics.Equals(END_CHAR_METRICS, StringComparison.Ordinal)) { throw new IOException("Error: Expected '" + END_CHAR_METRICS + "' actual '" + endCharMetrics + "'"); } charMetricsRead = true; fontMetrics.CharMetrics = charMetrics; break; case START_COMPOSITES: if (!reducedDataset) { int countComposites = ReadInt(); for (int i = 0; i < countComposites; i++) { Composite part = ParseComposite(); fontMetrics.AddComposite(part); } string endComposites = ReadString(); if (!endComposites.Equals(END_COMPOSITES, StringComparison.Ordinal)) { throw new IOException("Error: Expected '" + END_COMPOSITES + "' actual '" + endComposites + "'"); } } break; case START_KERN_DATA: if (!reducedDataset) { ParseKernData(fontMetrics); } break; default: if (reducedDataset && charMetricsRead) { break; } throw new IOException("Unknown AFM key '" + nextCommand + "'"); } } return(fontMetrics); }