/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { int version = data.ReadUnsignedShort(); if (version != 0) { version = (version << 16) | data.ReadUnsignedShort(); } int numSubtables = 0; if (version == 0) { numSubtables = data.ReadUnsignedShort(); } else if (version == 1) { numSubtables = (int)data.ReadUnsignedInt(); } else { Debug.WriteLine($"debug: Skipped kerning table due to an unsupported kerning table version: {version}"); } if (numSubtables > 0) { subtables = new KerningSubtable[numSubtables]; for (int i = 0; i < numSubtables; ++i) { KerningSubtable subtable = new KerningSubtable(); subtable.Read(data, version); subtables[i] = subtable; } } initialized = true; }
/** * Run the callback for each TT font in the collection. * * @param trueTypeFontProcessor the object with the callback method. * @ */ public void ProcessAllFonts(ITrueTypeFontProcessor trueTypeFontProcessor, object tag) { for (int i = 0; i < numFonts; i++) { TrueTypeFont font = GetFontAtIndex(i); trueTypeFontProcessor(font, tag); } }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @throws java.io.IOException If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { byte[] bytes = data.Read((int)Length); CFFParser parser = new CFFParser(); cffFont = parser.Parse(bytes, new CFFBytesource(font))[0]; initialized = true; }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { loca = ttf.IndexToLocation; numGlyphs = ttf.NumberOfGlyphs; glyphs = new Dictionary <int, GlyphData>(); // we don't actually read the complete table here because it can contain tens of thousands of glyphs this.data = data; initialized = true; }
/** * Get a TT font from a collection. * * @param name The postscript name of the font. * @return The found font, nor null if none is found. * @ */ public TrueTypeFont GetFontByName(string name) { for (int i = 0; i < numFonts; i++) { TrueTypeFont font = GetFontAtIndex(i); if (font.Name.Equals(name, StringComparison.Ordinal)) { return(font); } } return(null); }
/** * Creates a subsetter for the given font. * * @param ttf the font to be subset * @param tables optional tables to keep if present */ public TTFSubsetter(TrueTypeFont ttf, List <string> tables) { this.ttf = ttf; this.keepTables = tables; uniToGID = new SortedDictionary <int, int>(); glyphIds = new SortedSet <int>(); // find the best Unicode cmap this.unicodeCmap = ttf.GetUnicodeCmapLookup(); // always copy GID 0 glyphIds.Add(0); }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { version = data.Read32Fixed(); defaultVertOriginY = data.ReadSignedShort(); int numVertOriginYMetrics = data.ReadUnsignedShort(); origins = new Dictionary <int, int>(numVertOriginYMetrics); for (int i = 0; i < numVertOriginYMetrics; ++i) { int g = data.ReadUnsignedShort(); int y = data.ReadSignedShort(); origins[g] = y; } initialized = true; }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { HorizontalHeaderTable hHeader = ttf.HorizontalHeader; if (hHeader == null) { throw new IOException("Could not get hhea table"); } numHMetrics = hHeader.NumberOfHMetrics; int numGlyphs = ttf.NumberOfGlyphs; int bytesRead = 0; advanceWidth = new int[numHMetrics]; leftSideBearing = new short[numHMetrics]; for (int i = 0; i < numHMetrics; i++) { advanceWidth[i] = data.ReadUnsignedShort(); leftSideBearing[i] = data.ReadSignedShort(); bytesRead += 4; } int numberNonHorizontal = numGlyphs - numHMetrics; // handle bad fonts with too many hmetrics if (numberNonHorizontal < 0) { numberNonHorizontal = numGlyphs; } // make sure that table is never null and correct size, even with bad fonts that have no // "leftSideBearing" table although they should nonHorizontalLeftSideBearing = new short[numberNonHorizontal]; if (bytesRead < Length) { for (int i = 0; i < numberNonHorizontal; i++) { if (bytesRead < Length) { nonHorizontalLeftSideBearing[i] = data.ReadSignedShort(); bytesRead += 2; } } } initialized = true; }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { VerticalHeaderTable vHeader = ttf.VerticalHeader; if (vHeader == null) { throw new IOException("Could not get vhea table"); } numVMetrics = vHeader.NumberOfVMetrics; int numGlyphs = ttf.NumberOfGlyphs; int bytesRead = 0; advanceHeight = new int[numVMetrics]; topSideBearing = new short[numVMetrics]; for (int i = 0; i < numVMetrics; i++) { advanceHeight[i] = data.ReadUnsignedShort(); topSideBearing[i] = data.ReadSignedShort(); bytesRead += 4; } if (bytesRead < Length) { int numberNonVertical = numGlyphs - numVMetrics; // handle bad fonts with too many vmetrics if (numberNonVertical < 0) { numberNonVertical = numGlyphs; } additionalTopSideBearing = new short[numberNonVertical]; for (int i = 0; i < numberNonVertical; i++) { if (bytesRead < Length) { additionalTopSideBearing[i] = data.ReadSignedShort(); bytesRead += 2; } } } initialized = true; }
protected override TTFTable ReadTable(TrueTypeFont font, string tag) { // todo: this is a stub, a full implementation is needed switch (tag) { case "BASE": case "GDEF": case "GPOS": case "GSUB": case "JSTF": return(new OTLTable(font)); case "CFF ": return(new CFFTable(font)); default: return(base.ReadTable(font, tag)); } }
/** * Parse a file and get a true type font. * * @param raf The TTF file. * @return A TrueType font. * @ If there is an error parsing the TrueType font. */ public TrueTypeFont Parse(TTFDataStream raf, string fontName = null) { if (string.Equals(raf.ReadString(4), TrueTypeCollection.TAG, StringComparison.Ordinal)) { raf.Seek(raf.CurrentPosition - 4); TrueTypeCollection fontCollection = new TrueTypeCollection(raf); var nameFont = fontCollection.GetFontByName(fontName); if (nameFont == null) { nameFont = fontCollection.GetFontAtIndex(0); } return(nameFont); } raf.Seek(raf.CurrentPosition - 4); TrueTypeFont font = NewFont(raf); font.Version = raf.Read32Fixed(); int numberOfTables = raf.ReadUnsignedShort(); int searchRange = raf.ReadUnsignedShort(); int entrySelector = raf.ReadUnsignedShort(); int rangeShift = raf.ReadUnsignedShort(); for (int i = 0; i < numberOfTables; i++) { TTFTable table = ReadTableDirectory(font, raf); // skip tables with zero length if (table != null) { font.AddTable(table); } } // parse tables if wanted if (!parseOnDemandOnly) { ParseTables(font); } return(font); }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { version = data.Read32Fixed(); fontRevision = data.Read32Fixed(); checkSumAdjustment = data.ReadUnsignedInt(); magicNumber = data.ReadUnsignedInt(); flags = data.ReadUnsignedShort(); unitsPerEm = data.ReadUnsignedShort(); created = data.ReadInternationalDate(); modified = data.ReadInternationalDate(); xMin = data.ReadSignedShort(); yMin = data.ReadSignedShort(); xMax = data.ReadSignedShort(); yMax = data.ReadSignedShort(); macStyle = data.ReadUnsignedShort(); lowestRecPPEM = data.ReadUnsignedShort(); fontDirectionHint = data.ReadSignedShort(); indexToLocFormat = data.ReadSignedShort(); glyphDataFormat = data.ReadSignedShort(); initialized = true; }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { version = data.Read32Fixed(); ascender = data.ReadSignedShort(); descender = data.ReadSignedShort(); lineGap = data.ReadSignedShort(); advanceHeightMax = data.ReadUnsignedShort(); minTopSideBearing = data.ReadSignedShort(); minBottomSideBearing = data.ReadSignedShort(); yMaxExtent = data.ReadSignedShort(); caretSlopeRise = data.ReadSignedShort(); caretSlopeRun = data.ReadSignedShort(); caretOffset = data.ReadSignedShort(); reserved1 = data.ReadSignedShort(); reserved2 = data.ReadSignedShort(); reserved3 = data.ReadSignedShort(); reserved4 = data.ReadSignedShort(); metricDataFormat = data.ReadSignedShort(); numberOfVMetrics = data.ReadUnsignedShort(); initialized = true; }
public IndexToLocationTable(TrueTypeFont font) : base(font) { }
/** * Parse all tables and check if all needed tables are present. * * @param font the TrueTypeFont instance holding the parsed data. * @ If there is an error parsing the TrueType font. */ private void ParseTables(TrueTypeFont font) { foreach (TTFTable table in font.Tables) { if (!table.Initialized) { font.ReadTable(table); } } bool isPostScript = AllowCFF && font.TableMap.ContainsKey(CFFTable.TAG); HeaderTable head = font.Header; if (head == null) { throw new IOException("head is mandatory"); } HorizontalHeaderTable hh = font.HorizontalHeader; if (hh == null) { throw new IOException("hhead is mandatory"); } MaximumProfileTable maxp = font.MaximumProfile; if (maxp == null) { throw new IOException("maxp is mandatory"); } PostScriptTable post = font.PostScript; if (post == null && !isEmbedded) { // in an embedded font this table is optional throw new IOException("post is mandatory"); } if (!isPostScript) { IndexToLocationTable loc = font.IndexToLocation; if (loc == null) { throw new IOException("loca is mandatory"); } if (font.Glyph == null) { throw new IOException("glyf is mandatory"); } } if (font.Naming == null && !isEmbedded) { throw new IOException("name is mandatory"); } if (font.HorizontalMetrics == null) { throw new IOException("hmtx is mandatory"); } if (!isEmbedded && font.Cmap == null) { throw new IOException("cmap is mandatory"); } }
private TTFTable ReadTableDirectory(TrueTypeFont font, TTFDataStream raf) { TTFTable table; string tag = raf.ReadString(4); switch (tag) { case CmapTable.TAG: table = new CmapTable(font); break; case GlyphTable.TAG: table = new GlyphTable(font); break; case HeaderTable.TAG: table = new HeaderTable(font); break; case HorizontalHeaderTable.TAG: table = new HorizontalHeaderTable(font); break; case HorizontalMetricsTable.TAG: table = new HorizontalMetricsTable(font); break; case IndexToLocationTable.TAG: table = new IndexToLocationTable(font); break; case MaximumProfileTable.TAG: table = new MaximumProfileTable(font); break; case NamingTable.TAG: table = new NamingTable(font); break; case OS2WindowsMetricsTable.TAG: table = new OS2WindowsMetricsTable(font); break; case PostScriptTable.TAG: table = new PostScriptTable(font); break; case DigitalSignatureTable.TAG: table = new DigitalSignatureTable(font); break; case KerningTable.TAG: table = new KerningTable(font); break; case VerticalHeaderTable.TAG: table = new VerticalHeaderTable(font); break; case VerticalMetricsTable.TAG: table = new VerticalMetricsTable(font); break; case VerticalOriginTable.TAG: table = new VerticalOriginTable(font); break; case GlyphSubstitutionTable.TAG: table = new GlyphSubstitutionTable(font); break; default: table = ReadTable(font, tag); break; } table.Tag = tag; table.CheckSum = raf.ReadUnsignedInt(); table.Offset = raf.ReadUnsignedInt(); table.Length = raf.ReadUnsignedInt(); // skip tables with zero length (except glyf) if (table.Length == 0 && !tag.Equals(GlyphTable.TAG, StringComparison.Ordinal)) { return(null); } return(table); }
public VerticalOriginTable(TrueTypeFont font) : base(font) { }
protected virtual TTFTable ReadTable(TrueTypeFont font, string tag) { // unknown table type but read it anyway. return(new TTFTable(font)); }
/** * Creates a subsetter for the given font. * * @param ttf the font to be subset */ public TTFSubsetter(TrueTypeFont ttf) : this(ttf, null) { }
public VerticalMetricsTable(TrueTypeFont font) : base(font) { }
public OS2WindowsMetricsTable(TrueTypeFont font) : base(font) { }
public KerningTable(TrueTypeFont font) : base(font) { }
public GlyphSubstitutionTable(TrueTypeFont font) : base(font) { }
/** * Constructor. * * @param font The font which contains this table. */ public TTFTable(TrueTypeFont font) { this.font = font; }
public GlyphTable(TrueTypeFont font) : base(font) { }
public PostScriptTable(TrueTypeFont font) : base(font) { }
public HeaderTable(TrueTypeFont font) : base(font) { }
public HorizontalMetricsTable(TrueTypeFont font) : base(font) { }
/** * This will read the required data from the stream. * * @param ttf The font that is being read. * @param data The stream to read the data from. * @ If there is an error reading the data. */ public override void Read(TrueTypeFont ttf, TTFDataStream data) { formatType = data.Read32Fixed(); italicAngle = data.Read32Fixed(); underlinePosition = data.ReadSignedShort(); underlineThickness = data.ReadSignedShort(); isFixedPitch = data.ReadUnsignedInt(); minMemType42 = data.ReadUnsignedInt(); maxMemType42 = data.ReadUnsignedInt(); mimMemType1 = data.ReadUnsignedInt(); maxMemType1 = data.ReadUnsignedInt(); if (formatType.CompareTo(1.0f) == 0) { /* * This TrueType font file contains exactly the 258 glyphs in the standard Macintosh TrueType. */ glyphNames = new string[WGL4Names.NUMBER_OF_MAC_GLYPHS]; Array.Copy(WGL4Names.MAC_GLYPH_NAMES, 0, glyphNames, 0, WGL4Names.NUMBER_OF_MAC_GLYPHS); } else if (formatType.CompareTo(2.0f) == 0) { int numGlyphs = data.ReadUnsignedShort(); int[] glyphNameIndex = new int[numGlyphs]; glyphNames = new string[numGlyphs]; int maxIndex = int.MinValue; for (int i = 0; i < numGlyphs; i++) { int index = data.ReadUnsignedShort(); glyphNameIndex[i] = index; // PDFBOX-808: Index numbers between 32768 and 65535 are // reserved for future use, so we should just ignore them if (index <= 32767) { maxIndex = Math.Max(maxIndex, index); } } string[] nameArray = null; if (maxIndex >= WGL4Names.NUMBER_OF_MAC_GLYPHS) { nameArray = new string[maxIndex - WGL4Names.NUMBER_OF_MAC_GLYPHS + 1]; for (int i = 0; i < maxIndex - WGL4Names.NUMBER_OF_MAC_GLYPHS + 1; i++) { int numberOfChars = data.ReadUnsignedByte(); nameArray[i] = data.ReadString(numberOfChars); } } for (int i = 0; i < numGlyphs; i++) { int index = glyphNameIndex[i]; if (index >= 0 && index < WGL4Names.NUMBER_OF_MAC_GLYPHS) { glyphNames[i] = WGL4Names.MAC_GLYPH_NAMES[index]; } else if (index >= WGL4Names.NUMBER_OF_MAC_GLYPHS && index <= 32767 && nameArray != null) { glyphNames[i] = nameArray[index - WGL4Names.NUMBER_OF_MAC_GLYPHS]; } else { // PDFBOX-808: Index numbers between 32768 and 65535 are // reserved for future use, so we should just ignore them glyphNames[i] = ".undefined"; } } } else if (formatType.CompareTo(2.5f) == 0) { int[] glyphNameIndex = new int[ttf.NumberOfGlyphs]; for (int i = 0; i < glyphNameIndex.Length; i++) { int offset = data.ReadSignedByte(); glyphNameIndex[i] = i + 1 + offset; } glyphNames = new string[glyphNameIndex.Length]; for (int i = 0; i < glyphNames.Length; i++) { int index = glyphNameIndex[i]; if (index >= 0 && index < WGL4Names.NUMBER_OF_MAC_GLYPHS) { string name = WGL4Names.MAC_GLYPH_NAMES[index]; if (name != null) { glyphNames[i] = name; } } else { Debug.WriteLine($"debug: incorrect glyph name index {index}, valid numbers 0..{WGL4Names.NUMBER_OF_MAC_GLYPHS}"); } } } else if (formatType.CompareTo(3.0f) == 0) { // no postscript information is provided. Debug.WriteLine($"debug: No PostScript name information is provided for the font {font.Name}"); } initialized = true; }
public VerticalHeaderTable(TrueTypeFont font) : base(font) { }