/** * This will parse a single CharMetric object from the stream. * * @return The next char metric input the stream. * * @throws IOException If there is an error reading from the stream. */ private CharMetric ParseCharMetric() { CharMetric charMetric = new CharMetric(); string metrics = ReadLine(); var metricsTokenizer = metrics.Split(new char[] { ' ' }); try { for (int i = 0; i < metricsTokenizer.Length;) { string nextCommand = metricsTokenizer[i++]; switch (nextCommand) { case CHARMETRICS_C: string charCodeC = metricsTokenizer[i++]; charMetric.CharacterCode = int.Parse(charCodeC); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_CH: //Is the hex string <FF> or FF, the spec is a little //unclear, wait and see if it breaks anything. string charCodeCH = metricsTokenizer[i++]; charMetric.CharacterCode = Convert.ToInt32(charCodeCH, BITS_IN_HEX); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_WX: charMetric.Wx = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_W0X: charMetric.W0x = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_W1X: charMetric.W1x = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_WY: charMetric.Wy = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_W0Y: charMetric.W0y = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_W1Y: charMetric.W1y = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_W: float[] w = new float[2]; w[0] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); w[1] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); charMetric.W = w; VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_W0: float[] w0 = new float[2]; w0[0] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); w0[1] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); charMetric.W0 = w0; VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_W1: float[] w1 = new float[2]; w1[0] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); w1[1] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); charMetric.W1 = w1; VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_VV: float[] vv = new float[2]; vv[0] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); vv[1] = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); charMetric.Vv = vv; VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_N: charMetric.Name = metricsTokenizer[i++]; VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_B: var box = new SKRect(); box.Left = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); box.Bottom = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); box.Right = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); box.Top = float.Parse(metricsTokenizer[i++], CultureInfo.InvariantCulture); charMetric.BoundingBox = box; VerifySemicolon(metricsTokenizer, ref i); break; case CHARMETRICS_L: Ligature lig = new Ligature(); lig.Successor = metricsTokenizer[i++]; lig.LigatureValue = metricsTokenizer[i++]; charMetric.AddLigature(lig); VerifySemicolon(metricsTokenizer, ref i); break; default: throw new IOException("Unknown CharMetrics command '" + nextCommand + "'"); } } } catch (Exception e) { throw new IOException("Error: Corrupt AFM document:" + e); } return(charMetric); }
/** * 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); }