Example #1
0
        private static Dictionary <uint, uint> LoadSegmentedCoverage(FontSource p)
        {
            var dic = new Dictionary <uint, uint>();

            // Skip format
            p.ReadUShort();

            // Skip reserved
            p.ReadUShort();

            var length = p.ReadUInt();

            var language = p.ReadUInt();

            var numGroups = p.ReadUInt();

            for (var i = 0; i < numGroups; i++)
            {
                var startCharCode = p.ReadUInt();
                var endCharCode   = p.ReadUInt();
                var startGlyphId  = p.ReadUInt();

                for (var c = startCharCode; c <= endCharCode; c++)
                {
                    dic[c] = startGlyphId;
                    startGlyphId++;
                }
            }

            return(dic);
        }
Example #2
0
        private static uint[] LoadIndexToLocation(FontSource p, uint tableOffset, ushort glyphCount, short indexToLocFormat)
        {
            p.Offset = tableOffset;

            var isLong = indexToLocFormat == 1;

            var n            = glyphCount + 1;
            var localOffsets = new uint[n];

            if (isLong)
            {
                for (var i = 0; i < n; i++)
                {
                    localOffsets[i] = p.ReadUInt();
                }
            }
            else
            {
                for (var i = 0; i < n; i++)
                {
                    localOffsets[i] = (uint)p.ReadUShort() * 2;
                }
            }

            return(localOffsets);
        }
Example #3
0
        private static Dictionary <uint, uint> LoadCharacterToGlyphIndexMappingTable(FontSource p, uint tableOffset)
        {
            p.Offset = tableOffset;

            var version         = p.ReadUShort();
            var numTables       = p.ReadUShort();
            var encodingRecords = new EncodingRecord[numTables];

            for (var i = 0; i < numTables; i++)
            {
                encodingRecords[i] = EncodingRecord.Load(p, tableOffset);
            }

            var targetRecordId = -1;

            for (var i = numTables - 1; i >= 0; i--)
            {
                var r = encodingRecords[i];
                if (r.PlatformID == 3 && (r.EncodingID == 0 || r.EncodingID == 1 || r.EncodingID == 10) ||
                    r.PlatformID == 0 && (r.EncodingID == 0 || r.EncodingID == 1 || r.EncodingID == 2 || r.EncodingID == 3 || r.EncodingID == 4))
                {
                    targetRecordId = i;
                    break;
                }
            }

            if (targetRecordId < 0)
            {
                throw new FontException("Encoding record not found.");
            }

            var targetRecord = encodingRecords[targetRecordId];

            if (targetRecord.SubTableFormat == 12)
            {
                p.Offset = tableOffset + targetRecord.Offset;
                return(LoadSegmentedCoverage(p));
            }

            if (targetRecord.SubTableFormat == 4)
            {
                p.Offset = tableOffset + targetRecord.Offset;
                return(LoadSegmentMappingToDeltaValues(p));
            }

            throw new FontException($"Unsupported format: {targetRecord.SubTableFormat}");
        }
Example #4
0
        private static Dictionary <uint, uint> LoadSegmentMappingToDeltaValues(FontSource p)
        {
            var dic = new Dictionary <uint, uint>();

            var offset = p.Offset;

            // Skip format
            p.ReadUShort();

            var length        = p.ReadUShort();
            var language      = p.ReadUShort();
            var segCount      = p.ReadUShort() >> 1;
            var searchRange   = p.ReadUShort();
            var entrySelector = p.ReadUShort();
            var rangeShift    = p.ReadUShort();

            var endCodeParser       = new FontSource(p.Bytes, offset + 14);
            var startCodeParser     = new FontSource(p.Bytes, (uint)(offset + 16 + segCount * 2));
            var idDeltaParser       = new FontSource(p.Bytes, (uint)(offset + 16 + segCount * 4));
            var idRangeOffsetParser = new FontSource(p.Bytes, (uint)(offset + 16 + segCount * 6));

            for (var i = 0; i < segCount - 1; i++)
            {
                var endCode       = endCodeParser.ReadUShort();
                var startCode     = startCodeParser.ReadUShort();
                var idDelta       = idDeltaParser.ReadShort();
                var idRangeOffset = idRangeOffsetParser.ReadUShort();

                for (var c = startCode; c <= endCode; c++)
                {
                    uint glyphIndex;
                    if (idRangeOffset != 0)
                    {
                        var glyphIndexOffset = idRangeOffsetParser.Offset - 2;
                        glyphIndexOffset += idRangeOffset;
                        glyphIndexOffset += (uint)(c - startCode) * 2;
                        p.Offset          = glyphIndexOffset;
                        glyphIndex        = p.ReadUShort();
                        if (glyphIndex != 0)
                        {
                            glyphIndex = (uint)(glyphIndex + idDelta) & 0xFFFF;
                        }
                    }
                    else
                    {
                        glyphIndex = (uint)(c + idDelta) & 0xFFFF;
                    }

                    dic[c] = glyphIndex;
                }
            }

            return(dic);
        }
Example #5
0
        private static void LoadHorizontalMetrics(FontModel font, FontSource p, uint tableOffset, int numberOfHMetrics, int numGlyphs)
        {
            ushort advancedWidth   = 0;
            short  leftSideBearing = 0;

            p.Offset = tableOffset;
            for (var i = 0; i < numGlyphs; i++)
            {
                if (i < numberOfHMetrics)
                {
                    advancedWidth   = p.ReadUShort();
                    leftSideBearing = p.ReadShort();
                }
                font._glyphs[i] = new GlyphInfo(advancedWidth, leftSideBearing);
            }
        }
Example #6
0
                public static GlyphComponent Load(FontSource p)
                {
                    var gc    = new GlyphComponent();
                    var flags = p.ReadUShort();

                    gc.GlyphId = p.ReadUShort();

                    if ((flags & 1) > 0)
                    {
                        if ((flags & 2) > 0)
                        {
                            gc.DX = p.ReadShort();
                            gc.DY = p.ReadShort();
                        }
                        else
                        {
                            gc.MatchedPoints = new[] { p.ReadUShort(), p.ReadUShort() };
                        }
                    }
                    else
                    {
                        if ((flags & 2) > 0)
                        {
                            gc.DX = p.ReadSByte();
                            gc.DY = p.ReadSByte();
                        }
                        else
                        {
                            gc.MatchedPoints = new[] { p.ReadUShort(), p.ReadUShort() };
                        }
                    }

                    if ((flags & 8) > 0)
                    {
                        gc.XScale = gc.YScale = p.ReadF2Dot14();
                    }
                    else if ((flags & 64) > 0)
                    {
                        gc.XScale = p.ReadF2Dot14();
                        gc.YScale = p.ReadF2Dot14();
                    }
                    else if ((flags & 128) > 0)
                    {
                        gc.XScale  = p.ReadF2Dot14();
                        gc.Scale01 = p.ReadF2Dot14();
                        gc.Scale10 = p.ReadF2Dot14();
                        gc.YScale  = p.ReadF2Dot14();
                    }

                    gc.MoreComponents = (flags & 32) > 0;

                    return(gc);
                }
Example #7
0
        private static void LoadFontHeader(FontSource p, uint tableOffset, out short indexToLocFormat, out ushort unitsPerEm)
        {
            p.Offset = tableOffset;

            p.ReadUShort();
            p.ReadUShort();
            p.ReadFixed();
            p.ReadUInt();
            p.ReadUInt();
            p.ReadUShort();
            unitsPerEm = p.ReadUShort();
            p.Offset  += 8 * 2;
            p.ReadShort();
            p.ReadShort();
            p.ReadShort();
            p.ReadShort();
            p.ReadUShort();
            p.ReadUShort();
            p.ReadShort();
            indexToLocFormat = p.ReadShort();
            p.ReadShort();
        }
Example #8
0
 private static ushort LoadGlyphCount(FontSource p, uint tableOffset)
 {
     p.Offset = tableOffset + 4;
     return(p.ReadUShort());
 }
Example #9
0
 private static ushort LoadNumberOfHMetrics(FontSource p, uint tableOffset)
 {
     p.Offset = tableOffset + 34;
     return(p.ReadUShort());
 }
Example #10
0
            public       GlyphPoint[] GetGlyphPoints(FontSource source)
            {
                source.Offset = Offset;
                var endPtsOfContours = new ushort[NumberOfContours];

                for (var i = 0; i < NumberOfContours; i++)
                {
                    endPtsOfContours[i] = source.ReadUShort();
                }

                //instructionLength = data.ReadUShort();
                //instructions = new byte[instructionLength];
                //for (var i = 0; i < instructionLength; i++) instructions[i] = data.ReadByte();

                // Ignore instructions.
                var instructionLength = source.ReadUShort();

                source.Offset += instructionLength;

                var numberOfCoordinates = endPtsOfContours[endPtsOfContours.Length - 1] + 1;
                var points = new List <GlyphPoint>(numberOfCoordinates);

                for (var i = 0; i < numberOfCoordinates; i++)
                {
                    var flag       = source.ReadByte();
                    var glyphPoint = new GlyphPoint(flag);
                    points.Add(glyphPoint);
                    if (glyphPoint.IsRepeat)
                    {
                        var count = source.ReadByte();
                        for (var k = 0; k < count; k++)
                        {
                            points.Add(new GlyphPoint(flag));
                            i++;
                        }
                    }
                }

                foreach (var ep in endPtsOfContours)
                {
                    points[ep].IsEndPoint = true;
                }

                short xSum = 0;
                short ySum = 0;

                // Read X
                foreach (var point in points)
                {
                    var flag     = point.Flag;
                    var isShortX = GetFlag(flag, 1);
                    var isSameX  = GetFlag(flag, 4);
                    if (isShortX)
                    {
                        if (isSameX)
                        {
                            xSum += source.ReadByte();
                        }
                        else
                        {
                            xSum += (short)-source.ReadByte();
                        }
                    }
                    else
                    {
                        if (!isSameX)
                        {
                            xSum += source.ReadShort();
                        }
                    }

                    point.X = xSum;
                }

                // Read Y
                foreach (var point in points)
                {
                    var flag     = point.Flag;
                    var isShortY = GetFlag(flag, 2);
                    var isSameY  = GetFlag(flag, 5);
                    if (isShortY)
                    {
                        if (isSameY)
                        {
                            ySum += source.ReadByte();
                        }
                        else
                        {
                            ySum += (short)-source.ReadByte();
                        }
                    }
                    else
                    {
                        if (!isSameY)
                        {
                            ySum += source.ReadShort();
                        }
                    }

                    point.Y = ySum;
                }

                return(points.ToArray());
            }