Exemple #1
0
        private static TopDict[] LoadTopDicts(FontSource p, uint offset, ByteSegment[] cffIndex, ByteSegment[] strings)
        {
            var arr = new TopDict[cffIndex.Length];

            for (var i = 0; i < cffIndex.Length; i++)
            {
                var bsi           = cffIndex[i];
                var topDict       = CffDictParser.LoadTopDict(p.Bytes, bsi.Offset, bsi.Count, strings);
                var privateSize   = topDict.Private[0];
                var privateOffset = topDict.Private[1];
                if (privateSize != 0 && privateOffset != 0)
                {
                    var privateDict =
                        CffDictParser.LoadPrivateDict(p.Bytes, privateOffset + offset, privateSize);
                    topDict.DefaultWidthX = privateDict.DefaultWidthX;
                    topDict.NormalWidthX  = privateDict.NormalWidthX;
                    if (privateDict.Subrs != 0)
                    {
                        var subrOffset = privateOffset + privateDict.Subrs;
                        p.Offset = subrOffset + offset;
                        var subrIndex = LoadIndexData(p);
                        topDict.Subrs     = subrIndex;
                        topDict.SubrsBias = GetSubrBias(topDict.Subrs.Length);
                    }

                    topDict.PrivateDict = privateDict;
                }

                arr[i] = topDict;
            }
            return(arr);
        }
Exemple #2
0
        private void Load(ByteSegment segment, byte[] fontSource)
        {
            var i = 0;

            while (i < segment.Count)
            {
                var b0 = fontSource[segment.Offset + i];
                i++;

                if (b0 == 12)
                {
                    var b1 = fontSource[segment.Offset + i++];

                    switch (b1)
                    {
                    case 34:
                    {
                        // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
                        _path.Add(_vs.Shift(), 0);
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), 0);
                        _path.Add(_vs.Shift(), 0);
                        _path.Add(_vs.Shift(), 0);
                        _path.Add(_vs.Shift(), 0);
                        break;
                    }

                    case 35:
                    {
                        // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        break;
                    }

                    case 36:
                    {
                        // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), 0);
                        _path.Add(_vs.Shift(), 0);
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), 0);
                        break;
                    }

                    case 37:
                    {
                        // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 flex1 (12 37) |-
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), _vs.Shift());
                        _path.Add(_vs.Shift(), 0);
                        break;
                    }

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
                else if (b0 <= 27 || 29 <= b0 && b0 <= 31)
                {
                    switch (b0)
                    {
                    case 1:
                        // |- y dy {dya dyb}* hstem (1) |-
                        LoadStems();
                        break;

                    case 3:
                        // |- x dx {dxa dxb}* vstem (3) |-
                        LoadStems();
                        break;

                    case 4:
                        // |- dy1 vmoveto (4) |-
                        if (_vs.Count > 1 && !_haveWidth)
                        {
                            _width     = (int)_vs.Shift() + _normalWidthX;
                            _haveWidth = true;
                        }

                        _path.NewContour(0, _vs.Shift());
                        //_lastPoint.y += _vs.Pop();
                        //NewContour(_lastPoint);
                        break;

                    case 5:
                    {
                        // |- {dxa dya}+ rlineto (5) |-
                        while (_vs.Count > 0)
                        {
                            _path.Add(_vs.Shift(), _vs.Shift());
                        }

                        break;
                    }

                    case 6:
                    {
                        // |- dx1 {dya dxb}* hlineto (6) |-
                        // |- {dxa dyb}+ hlineto (6) |-
                        while (_vs.Count > 0)
                        {
                            _path.Add(_vs.Shift(), 0);
                            if (_vs.Count == 0)
                            {
                                break;
                            }

                            _path.Add(0, _vs.Shift());
                        }

                        break;
                    }

                    case 7:
                    {
                        // |- dy1 {dxa dyb}* vlineto (7) |-
                        // |- {dya dxb}+ vlineto (7) |-
                        while (_vs.Count > 0)
                        {
                            _path.Add(0, _vs.Shift());
                            if (_vs.Count == 0)
                            {
                                break;
                            }

                            _path.Add(_vs.Shift(), 0);
                        }

                        break;
                    }

                    case 8:
                    {
                        // |- {dxa dya dxb dyb dxc dyc}+ rrcurveto (8) |-
                        while (_vs.Count > 0)
                        {
                            _path.Add(_vs.Shift(), _vs.Shift(), true);
                            _path.Add(_vs.Shift(), _vs.Shift(), true);
                            _path.Add(_vs.Shift(), _vs.Shift());
                        }

                        break;
                    }

                    case 10:
                        // callsubr
                        var lIndex = (int)_vs.Pop() + _lsubrsBias;
                        Load(_lsubrs[lIndex], fontSource);
                        break;

                    case 11:
                        // return
                        break;

                    case 12:
                        // escape
                        break;

                    case 14:
                        // End of charstring
                        if (_vs.Count > 0 && !_haveWidth)
                        {
                            _width     = (int)_vs.Shift() + _normalWidthX;
                            _haveWidth = true;
                        }

                        break;

                    case 18:
                        LoadStems();
                        break;

                    case 19:
                    case 20:
                        // hintmask, cntrmask
                        LoadStems();
                        i += (_nStems + 7) >> 3;
                        break;

                    case 21:
                        // |- dx1 dy1 rmoveto (21) |-
                        if (_vs.Count > 2 && !_haveWidth)
                        {
                            _width     = (int)_vs.Shift() + _normalWidthX;
                            _haveWidth = true;
                        }

                        _path.NewContour(_vs.Shift(), _vs.Shift());
                        break;

                    case 22:
                        // |- dx1 hmoveto (22) |-
                        if (_vs.Count > 1 && !_haveWidth)
                        {
                            _width     = (int)_vs.Shift() + _normalWidthX;
                            _haveWidth = true;
                        }

                        _path.NewContour(_vs.Shift(), 0);
                        break;

                    case 23:
                        LoadStems();
                        break;

                    case 24:
                    {
                        // |- {dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline (24) |-

                        // Curve
                        while (_vs.Count > 4)
                        {
                            _path.Add(_vs.Shift(), _vs.Shift(), true);
                            _path.Add(_vs.Shift(), _vs.Shift(), true);
                            _path.Add(_vs.Shift(), _vs.Shift());
                        }

                        // Line
                        _path.Add(_vs.Shift(), _vs.Shift());
                        break;
                    }

                    case 25:
                    {
                        // |- {dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve (25) |-

                        // Lines
                        while (_vs.Count > 6)
                        {
                            _path.Add(_vs.Shift(), _vs.Shift());
                        }

                        // Curves
                        _path.Add(_vs.Shift(), _vs.Shift(), true);
                        _path.Add(_vs.Shift(), _vs.Shift(), true);
                        _path.Add(_vs.Shift(), _vs.Shift());
                        break;
                    }

                    case 26:
                    {
                        // |- dx1? {dya dxb dyb dyc}+ vvcurveto (26) |-
                        var dx = 0f;
                        if (_vs.Count % 2 == 1)
                        {
                            dx = _vs.Shift();
                        }
                        while (_vs.Count > 0)
                        {
                            _path.Add(dx, _vs.Shift(), true);
                            _path.Add(_vs.Shift(), _vs.Shift(), true);
                            _path.Add(0, _vs.Shift());
                            dx = 0;
                        }

                        break;
                    }

                    case 27:
                    {
                        // |- dy1? {dxa dxb dyb dxc}+ hhcurveto (27) |-
                        var dy1 = 0f;
                        if (_vs.Count % 2 == 1)
                        {
                            dy1 = _vs.Shift();
                        }
                        while (_vs.Count != 0)
                        {
                            _path.Add(_vs.Shift(), dy1, true);
                            _path.Add(_vs.Shift(), _vs.Shift(), true);
                            _path.Add(_vs.Shift(), 0);
                            dy1 = 0;
                        }

                        break;
                    }

                    case 28:
                        break;

                    case 29:
                        // callgsubr
                        var gIndex = (int)_vs.Pop() + _gsubrsBias;
                        Load(_gsubrs[gIndex], fontSource);
                        break;

                    case 30:
                    {
                        // |- dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30) |-
                        // |- {dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto (30) |-
                        var even = true;
                        while (_vs.Count >= 4)
                        {
                            if (even)
                            {
                                _path.Add(0, _vs.Shift(), true);
                                _path.Add(_vs.Shift(), _vs.Shift(), true);
                                _path.Add(_vs.Shift(), 0);
                            }
                            else
                            {
                                _path.Add(_vs.Shift(), 0, true);
                                _path.Add(_vs.Shift(), _vs.Shift(), true);
                                _path.Add(0, _vs.Shift());
                            }

                            even = !even;
                        }

                        if (_vs.Count == 1)
                        {
                            _path.ReplaceLastPoint(
                                _path.LastPoint.x + (even ? _vs.Shift() : 0),
                                _path.LastPoint.y + (even ? 0 : _vs.Shift())
                                );
                        }

                        break;
                    }

                    case 31:
                    {
                        // |- dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf? hvcurveto (31) |-
                        // |- {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf? hvcurveto (31) |-
                        var even = true;
                        while (_vs.Count >= 4)
                        {
                            if (even)
                            {
                                _path.Add(_vs.Shift(), 0, true);
                                _path.Add(_vs.Shift(), _vs.Shift(), true);
                                _path.Add(0, _vs.Shift());
                            }
                            else
                            {
                                _path.Add(0, _vs.Shift(), true);
                                _path.Add(_vs.Shift(), _vs.Shift(), true);
                                _path.Add(_vs.Shift(), 0);
                            }

                            even = !even;
                        }

                        if (_vs.Count == 1)
                        {
                            _path.ReplaceLastPoint(
                                _path.LastPoint.x + (even ? 0 : _vs.Shift()),
                                _path.LastPoint.y + (even ? _vs.Shift() : 0)
                                );
                        }

                        break;
                    }

                    default:
                        throw new ArgumentOutOfRangeException($"Invalid operator: {b0}");
                    }
                }
                // Operands
                else if (32 <= b0 && b0 <= 246)
                {
                    var val = b0 - 139;
                    _vs.Push(val);
                }
                else if (247 <= b0 && b0 <= 250)
                {
                    var b1  = fontSource[segment.Offset + i++];
                    var val = (b0 - 247) * 256 + b1 + 108;
                    _vs.Push(val);
                }
                else if (251 <= b0 && b0 <= 254)
                {
                    var b1  = fontSource[segment.Offset + i++];
                    var val = -(b0 - 251) * 256 - b1 - 108;
                    _vs.Push(val);
                }
                else if (b0 == 28)
                {
                    var b1  = fontSource[segment.Offset + i++];
                    var b2  = fontSource[segment.Offset + i++];
                    var val = CffDictParser.TwosComp((b1 << 8) | b2, 16);
                    _vs.Push(val);
                }
                else if (b0 == 255)
                {
                    var b1  = fontSource[segment.Offset + i++];
                    var b2  = fontSource[segment.Offset + i++];
                    var b3  = fontSource[segment.Offset + i++];
                    var b4  = fontSource[segment.Offset + i++];
                    var val = CffDictParser.TwosComp((b1 << 24) | (b2 << 16) | (b3 << 8) | b4, 32) /
                              (float)Math.Pow(2, 16);
                    _vs.Push(val);
                }
                else
                {
                    throw new FontException(string.Format("Invalid data: {0}(0x{0:X2})", b0));
                }
            }
        }
Exemple #3
0
        private CompactFontFormatTable(FontSource source, FontModel font)
        {
            var tableOffset = source.Offset;

            // Header
            // Skip h_major, h_minor, h_hdrSize, h_offSize
            source.Offset += 4;

            // Ignore Name Index
            LoadIndexData(source);

            // Top Dict Index
            var topDictIndex = LoadIndexData(source);

            // String Index
            var stringIndex = LoadIndexData(source);

            var globalSubrIndex = LoadIndexData(source);

            if (globalSubrIndex != null)
            {
                font.GSubrs     = globalSubrIndex;
                font.GSubrsBias = GetSubrBias(font.GSubrs.Length);
            }

            var topDictArray = LoadTopDicts(source, tableOffset, topDictIndex, stringIndex);

            if (topDictArray.Length != 1)
            {
                throw new FontException($"Too Many TopDict: {topDictArray.Length}");
            }

            font.TopDict = topDictArray[0];

            if (font.TopDict.PrivateDict != null)
            {
                font.DefaultWidthX = font.TopDict.PrivateDict.DefaultWidthX;
                font.NormalWidthX  = font.TopDict.PrivateDict.NormalWidthX;
            }

            font.IsCidFont = font.TopDict.ROS.Item1 != null && font.TopDict.ROS.Item2 != null;

            if (font.IsCidFont)
            {
                if (!font.TopDict.FDArrayIndex.HasValue || font.TopDict.FDArrayIndex.Value == 0)
                {
                    throw new FontException("FDArray is missing.");
                }

                if (!font.TopDict.FDSelectIndex.HasValue || font.TopDict.FDSelectIndex.Value == 0)
                {
                    throw new FontException("FDSelect is missing");
                }

                var fdArrayOffset  = tableOffset + font.TopDict.FDArrayIndex.Value;
                var fdSelectOffset = tableOffset + font.TopDict.FDSelectIndex.Value;

                source.Offset = fdArrayOffset;
                var fdArrayIndex = LoadIndexData(source);
                font.TopDict.FDArray =
                    LoadTopDicts(source, tableOffset, fdArrayIndex, stringIndex);
                font.TopDict.FDSelect =
                    LoadFdSelect(source, fdSelectOffset, font.GlyphCount, (uint)font.TopDict.FDArray.Length);
            }

            var privateDictOffset = tableOffset + font.TopDict.Private[1];
            var privateDict       = CffDictParser.LoadPrivateDict(source.Bytes, privateDictOffset, font.TopDict.Private[0]);

            font.DefaultWidthX = privateDict.DefaultWidthX;
            font.NormalWidthX  = privateDict.NormalWidthX;

            if (privateDict.Subrs != 0)
            {
                var subrOffset = privateDictOffset + privateDict.Subrs;
                source.Offset = subrOffset;
                var subrIndex = LoadIndexData(source);
                font.Subrs     = subrIndex;
                font.SubrsBias = GetSubrBias(font.Subrs.Length);
            }
            else
            {
                font.Subrs     = new ByteSegment[0];
                font.SubrsBias = 0;
            }

            source.Offset    = tableOffset + font.TopDict.CharStrings;
            _charStringIndex = LoadIndexData(source);
        }