Example #1
0
        /**
         * Constructor.
         *
         * @param bais the stream to be read
         * @param glyphTable the Glyphtable containing all glyphs
         * @ is thrown if something went wrong
         */
        public GlyfCompositeDescript(TTFDataStream bais, GlyphTable glyphTable)
            : base((short)-1, bais)
        {
            this.glyphTable = glyphTable;

            // Get all of the composite components
            GlyfCompositeComp comp;

            do
            {
                comp = new GlyfCompositeComp(bais);
                components.Add(comp);
            }while ((comp.Flags & GlyfCompositeComp.MORE_COMPONENTS) != 0);

            // Are there hinting instructions to read?
            if ((comp.Flags & GlyfCompositeComp.WE_HAVE_INSTRUCTIONS) != 0)
            {
                ReadInstructions(bais, (bais.ReadUnsignedShort()));
            }
            InitDescriptions();
        }
Example #2
0
        /**
         * This will read the required data from the stream.
         *
         * @param glyphTable The glyph table this glyph belongs to.
         * @param data The stream to read the data from.
         * @param leftSideBearing The left side bearing for this glyph.
         * @ If there is an error reading the data.
         */
        public void InitData(GlyphTable glyphTable, TTFDataStream data, int leftSideBearing)
        {
            numberOfContours = data.ReadSignedShort();
            xMin             = data.ReadSignedShort();
            yMin             = data.ReadSignedShort();
            xMax             = data.ReadSignedShort();
            yMax             = data.ReadSignedShort();
            boundingBox      = new SKRect(xMin, yMin, xMax, yMax);

            if (numberOfContours >= 0)
            {
                // create a simple glyph
                short x0 = (short)(leftSideBearing - xMin);
                glyphDescription = new GlyfSimpleDescript(numberOfContours, data, x0);
            }
            else
            {
                // create a composite glyph
                glyphDescription = new GlyfCompositeDescript(data, glyphTable);
            }
        }
Example #3
0
        // never returns null
        private byte[] BuildGlyfTable(long[] newOffsets)
        {
            GlyphTable g = ttf.Glyph;

            long[]       offsets = ttf.IndexToLocation.Offsets;
            MemoryStream bos     = new MemoryStream();

            using (Bytes.Buffer input = ttf.OriginalData)
            {
                long isResult = input.Skip(g.Offset);

                if (isResult.CompareTo(g.Offset) != 0)
                {
                    Debug.WriteLine($"debug: Tried skipping {g.Offset} bytes but skipped only {isResult} bytes");
                }

                long prevEnd   = 0;  // previously read glyph offset
                long newOffset = 0;  // new offset for the glyph in the subset font
                int  newGid    = 0;  // new GID in subset font

                // for each glyph in the subset
                foreach (int gid in glyphIds)
                {
                    long offset = offsets[gid];
                    long length = offsets[gid + 1] - offset;

                    newOffsets[newGid++] = newOffset;
                    isResult             = input.Skip(offset - prevEnd);

                    if (isResult.CompareTo(offset - prevEnd) != 0)
                    {
                        Debug.WriteLine($"debug: Tried skipping {(offset - prevEnd)} bytes but skipped only {isResult} bytes");
                    }

                    sbyte[] buf = new sbyte[(int)length];
                    isResult = input.Read(buf);

                    if (isResult.CompareTo(length) != 0)
                    {
                        Debug.WriteLine($"debug: Tried reading {length} bytes but only {isResult} bytes read");
                    }

                    // detect glyph type
                    if (buf.Length >= 2 && buf[0] == -1 && buf[1] == -1)
                    {
                        // compound glyph
                        int off = 2 * 5;
                        int flags;
                        do
                        {
                            // flags
                            flags = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff;
                            off  += 2;

                            // glyphIndex
                            int componentGid = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff;
                            if (!glyphIds.Contains(componentGid))
                            {
                                glyphIds.Add(componentGid);
                            }

                            int newComponentGid = GetNewGlyphId(componentGid);
                            buf[off]     = (sbyte)((uint)(newComponentGid) >> 8);
                            buf[off + 1] = (sbyte)newComponentGid;
                            off         += 2;

                            // ARG_1_AND_2_ARE_WORDS
                            if ((flags & 1 << 0) != 0)
                            {
                                off += 2 * 2;
                            }
                            else
                            {
                                off += 2;
                            }
                            // WE_HAVE_A_TWO_BY_TWO
                            if ((flags & 1 << 7) != 0)
                            {
                                off += 2 * 4;
                            }
                            // WE_HAVE_AN_X_AND_Y_SCALE
                            else if ((flags & 1 << 6) != 0)
                            {
                                off += 2 * 2;
                            }
                            // WE_HAVE_A_SCALE
                            else if ((flags & 1 << 3) != 0)
                            {
                                off += 2;
                            }
                        }while ((flags & 1 << 5) != 0); // MORE_COMPONENTS

                        // WE_HAVE_INSTRUCTIONS
                        if ((flags & 0x0100) == 0x0100)
                        {
                            // USHORT numInstr
                            int numInstr = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff;
                            off += 2;

                            // BYTE instr[numInstr]
                            off += numInstr;
                        }

                        // write the compound glyph
                        bos.Write((byte[])(Array)buf, 0, off);

                        // offset to start next glyph
                        newOffset += off;
                    }
                    else if (buf.Length > 0)
                    {
                        // copy the entire glyph
                        bos.Write((byte[])(Array)buf, 0, buf.Length);

                        // offset to start next glyph
                        newOffset += buf.Length;
                    }

                    // 4-byte alignment
                    if (newOffset % 4 != 0)
                    {
                        int len = 4 - (int)(newOffset % 4);
                        bos.Write(PAD_BUF, 0, len);
                        newOffset += len;
                    }

                    prevEnd = offset + length;
                }
                newOffsets[newGid++] = newOffset;
            }

            return(bos.ToArray());
        }
Example #4
0
        /**
         * Resolve compound glyph references.
         */
        private void AddCompoundReferences()
        {
            if (hasAddedCompoundReferences)
            {
                return;
            }
            hasAddedCompoundReferences = true;

            bool hasNested;

            do
            {
                GlyphTable   g             = ttf.Glyph;
                long[]       offsets       = ttf.IndexToLocation.Offsets;
                Bytes.Buffer input         = ttf.OriginalData;
                ISet <int>   glyphIdsToAdd = null;
                try
                {
                    long isResult = input.Skip(g.Offset);

                    if (isResult.CompareTo(g.Offset) != 0)
                    {
                        Debug.WriteLine($"debug: Tried skipping {g.Offset} bytes but skipped only {isResult} bytes");
                    }

                    long lastOff = 0L;
                    foreach (int glyphId in glyphIds)
                    {
                        long offset = offsets[glyphId];
                        long len    = offsets[glyphId + 1] - offset;
                        isResult = input.Skip(offset - lastOff);

                        if (isResult.CompareTo(offset - lastOff) != 0)
                        {
                            Debug.WriteLine($"debug: Tried skipping {(offset - lastOff)} bytes but skipped only {isResult} bytes");
                        }

                        sbyte[] buf = new sbyte[(int)len];
                        isResult = input.Read(buf);

                        if (isResult.CompareTo(len) != 0)
                        {
                            Debug.WriteLine($"debug: Tried reading {len} bytes but only {isResult} bytes read");
                        }

                        // rewrite glyphIds for compound glyphs
                        if (buf.Length >= 2 && buf[0] == -1 && buf[1] == -1)
                        {
                            int off = 2 * 5;
                            int flags;
                            do
                            {
                                flags = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff;
                                off  += 2;
                                int ogid = (buf[off] & 0xff) << 8 | buf[off + 1] & 0xff;
                                if (!glyphIds.Contains(ogid))
                                {
                                    if (glyphIdsToAdd == null)
                                    {
                                        glyphIdsToAdd = new HashSet <int>();
                                    }
                                    glyphIdsToAdd.Add(ogid);
                                }
                                off += 2;
                                // ARG_1_AND_2_ARE_WORDS
                                if ((flags & 1 << 0) != 0)
                                {
                                    off += 2 * 2;
                                }
                                else
                                {
                                    off += 2;
                                }
                                // WE_HAVE_A_TWO_BY_TWO
                                if ((flags & 1 << 7) != 0)
                                {
                                    off += 2 * 4;
                                }
                                // WE_HAVE_AN_X_AND_Y_SCALE
                                else if ((flags & 1 << 6) != 0)
                                {
                                    off += 2 * 2;
                                }
                                // WE_HAVE_A_SCALE
                                else if ((flags & 1 << 3) != 0)
                                {
                                    off += 2;
                                }
                            }while ((flags & 1 << 5) != 0); // MORE_COMPONENTS
                        }
                        lastOff = offsets[glyphId + 1];
                    }
                }
                finally
                {
                    input.Dispose();
                }
                if (glyphIdsToAdd != null)
                {
                    glyphIds.AddAll(glyphIdsToAdd);
                }
                hasNested = glyphIdsToAdd != null;
            }while (hasNested);
        }
Example #5
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);
        }