Beispiel #1
0
        public static FpgmTable Read(FontStreamReader reader, OffsetTable.Entry entry)
        {
            reader.Seek(entry);

            var instructions = reader.ReadArray <byte>(entry.Length, r => r.ReadUInt8);

            return(new FpgmTable(instructions));
        }
Beispiel #2
0
        public static CmapFormat Read(FontStreamReader reader, ushort platformId, ushort platformSpecificId)
        {
            var length   = reader.ReadUInt16();
            var language = reader.ReadUInt16();

            var glyphIndexArray = reader.ReadArray <byte>(256, r => r.ReadUInt8);

            return(new CmapFormat0(language, glyphIndexArray));
        }
Beispiel #3
0
        public static LocaTable Read(Font font, FontStreamReader reader, OffsetTable.Entry entry)
        {
            reader.Seek(entry);

            var length = entry.Length;
            var format = font.HeadTable.IndexToLocFormat;

            switch (format)
            {
            case IndexToLocFormat.Short:
                return(new LocaTable(reader.ReadArray <uint>(length / sizeof(ushort), r => (() => r.ReadUInt16()))));

            case IndexToLocFormat.Long:
                return(new LocaTable(reader.ReadArray <uint>(length / sizeof(uint), r => r.ReadUInt32)));

            default: throw new FormatException($"Invalid IndexToLocFormat: {format}");
            }
        }
Beispiel #4
0
        public static CmapFormat Read(FontStreamReader reader, ushort platformId, ushort platformSpecificId)
        {
            uint length   = reader.ReadUInt16();
            var  language = reader.ReadUInt16();

            length -= 3 * sizeof(ushort);

            var segCount = (ushort)(reader.ReadUInt16() / 2); // stored as 2 * segCount

            var searchRange   = reader.ReadUInt16();
            var entrySelector = reader.ReadUInt16();
            var rangeShift    = reader.ReadUInt16();

            length -= 4 * sizeof(ushort);

            var endCode = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16);

            if (endCode[endCode.Length - 1] != 0xffff)
            {
                throw new FormatException($"Unexpected last endCode: 0x{endCode[endCode.Length - 1]:X}, expecting 0xffff");
            }

            var reservedPad = reader.ReadUInt16(); // 0

            if (reservedPad != 0)
            {
                throw new FormatException($"Unexpected value for reservedPad: {reservedPad}, expecting 0");
            }

            length -= (ushort)(segCount * sizeof(ushort) + 1);

            var startCode     = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16);
            var idDelta       = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16);
            var idRangeOffset = reader.ReadArray <ushort>(segCount, r => r.ReadUInt16);

            length -= (ushort)(3 * segCount * sizeof(ushort));

            var glyphIndexArray = reader.ReadArray <ushort>(length / sizeof(ushort), r => r.ReadUInt16);

            return(new CmapFormat4(language, startCode, endCode, idDelta, idRangeOffset, glyphIndexArray));
        }
Beispiel #5
0
        private static Glyph ReadCompoundGlyph(FontStreamReader reader, ushort xMin, ushort yMin, ushort xMax, ushort yMax)
        {
            var components = new List <CompoundGlyph.Component>();

            var flags = GlyphComponentFlags.MoreComponents;

            while (flags.HasFlag(GlyphComponentFlags.MoreComponents))
            {
                flags = (GlyphComponentFlags)reader.ReadUInt16();
                var glyphIndex = reader.ReadInt16();

                if (flags.HasFlag(GlyphComponentFlags.WeHaveInstructions) && flags.HasFlag(GlyphComponentFlags.MoreComponents))
                {
                    throw new NotImplementedException();
                }

                var arg1 = flags.HasFlag(GlyphComponentFlags.Arg12AreWords) ? reader.ReadInt16() : reader.ReadUInt8();
                var arg2 = flags.HasFlag(GlyphComponentFlags.Arg12AreWords) ? reader.ReadInt16() : reader.ReadUInt8();

                var matrix = new decimal[] {
                    1, 0,
                    0, 1,
                    0, 0
                };

                short?destPointIndex = null;
                short?srcPointIndex  = null;

                if (flags.HasFlag(GlyphComponentFlags.ArgsAreXYValues))
                {
                    matrix[4] = arg1;
                    matrix[5] = arg2;
                }
                else
                {
                    destPointIndex = arg1;
                    srcPointIndex  = arg1;
                }

                if (flags.HasFlag(GlyphComponentFlags.WeHaveAScale))
                {
                    matrix[0] = matrix[3] = reader.ReadF2Dot14();
                }
                else if (flags.HasFlag(GlyphComponentFlags.WeHaveAnXYScale))
                {
                    matrix[0] = reader.ReadF2Dot14();
                    matrix[3] = reader.ReadF2Dot14();
                }
                else if (flags.HasFlag(GlyphComponentFlags.WeHave2By2))
                {
                    matrix[0] = reader.ReadF2Dot14();
                    matrix[1] = reader.ReadF2Dot14();
                    matrix[2] = reader.ReadF2Dot14();
                    matrix[3] = reader.ReadF2Dot14();
                }

                components.Add(new CompoundGlyph.Component(glyphIndex, matrix, destPointIndex, srcPointIndex));
            }

            var instructions = new byte[0];

            if (flags.HasFlag(GlyphComponentFlags.WeHaveInstructions))
            {
                var instructionLength = reader.ReadUInt16();
                instructions = reader.ReadArray <byte>(instructionLength, r => r.ReadUInt8);
            }

            return(new CompoundGlyph(components, instructions));
        }
Beispiel #6
0
        private static Glyph ReadSimpleGlyph(FontStreamReader reader, short numberOfContours, ushort xMin, ushort yMin, ushort xMax, ushort yMax)
        {
            var endPoints = reader.ReadArray <ushort>((ushort)numberOfContours, r => r.ReadUInt16);

            var instructionLength = reader.ReadUInt16();
            var instructions      = reader.ReadArray <byte>(instructionLength, r => r.ReadUInt8);

            if (numberOfContours == 0)
            {
                return(new SimpleGlyph(xMin, yMin, xMax, yMax, endPoints, instructions, new Point[0]));
            }

            var numberOfPoints = endPoints.Max() + 1;

            var flags  = new SimpleGlyphFlags[numberOfPoints];
            var points = new Point[numberOfPoints];

            for (var i = 0; i < numberOfPoints; i++)
            {
                var flag = (SimpleGlyphFlags)reader.ReadUInt8();
                flags[i]  = flag;
                points[i] = new Point {
                    OnCurve = flag.HasFlag(SimpleGlyphFlags.OnCurve)
                };

                if (flag.HasFlag(SimpleGlyphFlags.Repeat))
                {
                    var count = reader.ReadUInt8();
                    while (count-- > 0)
                    {
                        flags[++i] = flag;
                        points[i]  = new Point {
                            OnCurve = flag.HasFlag(SimpleGlyphFlags.OnCurve)
                        };
                    }
                }
            }

            // read X
            short value = 0;

            for (var i = 0; i < numberOfPoints; i++)
            {
                var flag = flags[i];

                if (flag.HasFlag(SimpleGlyphFlags.XShort))
                {
                    if (flag.HasFlag(SimpleGlyphFlags.XSame))
                    {
                        value += reader.ReadUInt8();
                    }
                    else
                    {
                        value -= reader.ReadUInt8();
                    }
                }
                else if (!flag.HasFlag(SimpleGlyphFlags.XSame))
                {
                    value += reader.ReadInt16();
                }

                points[i].X = value;
            }

            // read Y
            value = 0;
            for (var i = 0; i < numberOfPoints; i++)
            {
                var flag = flags[i];

                if (flag.HasFlag(SimpleGlyphFlags.YShort))
                {
                    if (flag.HasFlag(SimpleGlyphFlags.YSame))
                    {
                        value += reader.ReadUInt8();
                    }
                    else
                    {
                        value -= reader.ReadUInt8();
                    }
                }
                else if (!flag.HasFlag(SimpleGlyphFlags.YSame))
                {
                    value += reader.ReadInt16();
                }

                points[i].Y = value;
            }

            return(new SimpleGlyph(xMin, yMin, xMax, yMax, endPoints, instructions, points));
        }