private byte[] BuildPostTable()
        {
            PostScriptTable post = ttf.PostScript;

            if (post == null || keepTables != null && !keepTables.Contains("post", StringComparer.Ordinal))
            {
                return(null);
            }

            using (var bos = new MemoryStream())
                using (var output = new BinaryWriter(bos))
                {
                    WriteFixed(output, 2.0); // version
                    WriteFixed(output, post.ItalicAngle);
                    WriteSInt16(output, post.UnderlinePosition);
                    WriteSInt16(output, post.UnderlineThickness);
                    WriteUint32(output, post.IsFixedPitch);
                    WriteUint32(output, post.MinMemType42);
                    WriteUint32(output, post.MaxMemType42);
                    WriteUint32(output, post.MinMemType1);
                    WriteUint32(output, post.MaxMemType1);

                    // version 2.0

                    // numberOfGlyphs
                    WriteUint16(output, glyphIds.Count);

                    // glyphNameIndex[numGlyphs]
                    ConcurrentDictionary <string, int> names = new ConcurrentDictionary <string, int>(StringComparer.Ordinal);
                    foreach (int gid in glyphIds)
                    {
                        string name = post.GetName(gid);
                        if (WGL4Names.MAC_GLYPH_NAMES_INDICES.TryGetValue(name, out int macId))
                        {
                            // the name input implicit, as it's from MacRoman
                            WriteUint16(output, macId);
                        }
                        else
                        {
                            // the name will be written explicitly
                            int ordinal = names.GetOrAdd(name, (p) => names.Count);
                            WriteUint16(output, 258 + ordinal);
                        }
                    }

                    // names[numberNewGlyphs]
                    foreach (string name in names.Keys)
                    {
                        byte[] buf = Charset.ASCII.GetBytes(name);
                        WriteUint8(output, buf.Length);
                        output.Write(buf);
                    }

                    output.Flush();
                    return(bos.ToArray());
                }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        /**
         * 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");
            }
        }