Exemplo n.º 1
0
        public bool SetComponents(WoffReader reader)
        {
            uint startOffset        = reader.Offset;
            bool weHaveInstructions = false;

            ushort flags = MORE_COMPONENTS;

            while ((flags & MORE_COMPONENTS) > 0)
            {
                flags = reader.ReadUInt16();
                weHaveInstructions |= (flags & WE_HAVE_INSTRUCTIONS) != 0;
                ushort argSize = WoffBuffer.SizeOfUShort;   // 2-bytes glyph index
                if ((flags & ARG_1_AND_2_ARE_WORDS) > 0)
                {
                    argSize += WoffBuffer.SizeOfUShort * 2; // 4-bytes
                }
                else
                {
                    argSize += WoffBuffer.SizeOfUShort;     // 2-bytes
                }
                if ((flags & WE_HAVE_A_SCALE) > 0)
                {
                    argSize += WoffBuffer.SizeOfUShort;     // 2-bytes
                }
                else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) > 0)
                {
                    argSize += WoffBuffer.SizeOfUShort * 2; // 4-bytes
                }
                else if ((flags & WE_HAVE_A_TWO_BY_TWO) > 0)
                {
                    argSize += WoffBuffer.SizeOfUShort * 4; // 8-bytes
                }
                if (!reader.Skip(argSize))
                {
                    return(false);
                }
            }
            uint endOffset = reader.Offset;

            _hasInstructions = weHaveInstructions;

            _componentLength = (ushort)(endOffset - startOffset);
            _components      = reader.ReadByte(_componentLength, startOffset);

            Debug.Assert(reader.Offset == endOffset);

            return(reader.Offset == endOffset);
        }
Exemplo n.º 2
0
        private bool TransformHmtx()
        {
            var glyfTable = _woffFont.Tables[_glyfIndex] as WoffTableGlyf;

            Debug.Assert(glyfTable != null);
            if (glyfTable == null)
            {
                return(false);
            }

            if (_hheaIndex == -1 || _hmtxIndex == -1)
            {
                return(false);
            }

            var glyphs        = glyfTable.Glyphs;
            var glyphAdvances = glyfTable.GlyphsAdvances;

            var woffDirs = _woffFont.Directories;
            var hheaDir  = woffDirs[_hheaIndex];
            // Get numberOfHMetrics, https://www.microsoft.com/typography/otspec/hhea.htm
            var hheaReader = new WoffReader(hheaDir.OrigTable);

            // Skip 34 to reach 'hhea' numberOfHMetrics
            if (hheaReader.Skip(34) == false)
            {
                return(false);
            }
            ushort numOfHMetrics = hheaReader.ReadUInt16();

            var reader = new WoffReader(_woffDir.CompTable);
            var flags  = reader.ReadByte();

            // By the specs: When hmtx transform is indicated by the table directory,
            // the Flags (bits 0 or 1 or both) must be set.
            if ((flags & 0x01) != 1 && (flags & 0x02) != 1)
            {
                Trace.TraceError("Hmtx Compression Error: When hmtx transform is indicated by the table directory, "
                                 + "the Flags (bits 0 or 1 or both) must be set.");
                return(false);
            }
            // By the specs: Bits 2-7 are reserved and must be zero.
            if ((flags & 0xFC) != 0)
            {
                Trace.TraceError("Hmtx Compression Error: Bits 2-7 are reserved and must be zero.");
            }

            int numOfGlyphs = glyphs.Length;

            Debug.Assert(glyphAdvances.Length == numOfGlyphs);

            // The number of glyphs numGlyphs can be 0, if there is no 'glyf' but cannot then xform 'hmtx'.
            Debug.Assert(numOfHMetrics <= numOfGlyphs);
            if (numOfHMetrics > numOfGlyphs)
            {
                return(false);
            }

            // https://www.microsoft.com/typography/otspec/hmtx.htm
            // "...only one entry need be in the array, but that entry is required."
            if (numOfHMetrics < 1)
            {
                return(false);
            }

            bool hasProportionalLsbs = (flags & 0x01) == 0;
            bool hasMonospaceLsbs    = (flags & 0x02) == 0;

            IList <ushort> advanceWidths = new List <ushort>();
            IList <short>  lsbs          = new List <short>();

            for (ushort glyphIndex = 0; glyphIndex < numOfHMetrics; glyphIndex++)
            {
                advanceWidths.Add(reader.ReadUInt16());
            }

            for (ushort glyphIndex = 0; glyphIndex < numOfHMetrics; glyphIndex++)
            {
                if (hasProportionalLsbs)
                {
                    lsbs.Add(reader.ReadInt16());
                }
                else
                {
                    lsbs.Add(glyphAdvances[glyphIndex]);
                }
            }

            for (ushort glyphIndex = numOfHMetrics; glyphIndex < numOfGlyphs; glyphIndex++)
            {
                if (hasMonospaceLsbs)
                {
                    lsbs.Add(reader.ReadInt16());
                }
                else
                {
                    lsbs.Add(glyphAdvances[glyphIndex]);
                }
            }

            return(SerializeHmtx(advanceWidths, lsbs, numOfHMetrics, numOfGlyphs));
        }