internal void Run(IGlyphTranslator tx, Cff1Font cff1Font, Type2GlyphInstructionList instructionList, float scale = 1)
        {
            //all fields are set to new values***

            _cff1Font = cff1Font;
            _scale    = scale;

            //-------------
            //from Technical Note #5176 (CFF spec)
            //resolve with bias
            //Card16 bias;
            //Card16 nSubrs = subrINDEX.count;
            //if (CharstringType == 1)
            //    bias = 0;
            //else if (nSubrs < 1240)
            //    bias = 107;
            //else if (nSubrs < 33900)
            //    bias = 1131;
            //else
            //    bias = 32768;

            //find local subroutine

            int nsubrs = cff1Font._localSubrs.Count;

            _cffBias = (nsubrs < 1240) ? 107 :
                       (nsubrs < 33900) ? 1131 : 32769;      //TODO: review 32769 or 32768

            //
            double currentX = 0, currentY = 0;


            var scaleTx = new PxScaleGlyphTx(scale, tx);

            //
            scaleTx.BeginRead(0);//unknown contour count
            //
            Run(scaleTx, instructionList, ref currentX, ref currentY);
            //

            //
            //some cff end without closing the latest contour?

            if (scaleTx.IsContourOpened)
            {
                scaleTx.CloseContour();
            }

            scaleTx.EndRead();
        }
        void Run(IGlyphTranslator tx, Type2GlyphInstructionList instructionList, ref double currentX, ref double currentY)
        {
            //recursive ***

            Type2EvaluationStack evalStack = GetFreeEvalStack(); //**

            evalStack._currentX = currentX;
            evalStack._currentY = currentY;

            List <Type2Instruction> insts = instructionList.Insts;

            evalStack.GlyphTranslator = tx;
            int j = insts.Count;

            for (int i = 0; i < j; ++i)
            {
                Type2Instruction inst = insts[i];
                //if (inst.Op != OperatorName.LoadInt)
                //{
                //}
                switch (inst.Op)
                {
                default: throw new NotSupportedException();

                case OperatorName.GlyphWidth:
                    //TODO:
                    break;

                case OperatorName.LoadInt:
                    evalStack.Push(inst.Value);
                    break;                        //

                case OperatorName.endchar:
                    evalStack.EndChar();
                    break;

                case OperatorName.flex: evalStack.Flex(); break;

                case OperatorName.hflex: evalStack.H_Flex(); break;

                case OperatorName.hflex1: evalStack.H_Flex1(); break;

                case OperatorName.flex1: evalStack.Flex1(); break;

                //-------------------------
                //4.4: Arithmetic Operators
                case OperatorName.abs: evalStack.Op_Abs(); break;

                case OperatorName.add: evalStack.Op_Add(); break;

                case OperatorName.sub: evalStack.Op_Sub(); break;

                case OperatorName.div: evalStack.Op_Div(); break;

                case OperatorName.neg: evalStack.Op_Neg(); break;

                case OperatorName.random: evalStack.Op_Random(); break;

                case OperatorName.mul: evalStack.Op_Mul(); break;

                case OperatorName.sqrt: evalStack.Op_Sqrt(); break;

                case OperatorName.drop: evalStack.Op_Drop(); break;

                case OperatorName.exch: evalStack.Op_Exch(); break;

                case OperatorName.index: evalStack.Op_Index(); break;

                case OperatorName.roll: evalStack.Op_Roll(); break;

                case OperatorName.dup: evalStack.Op_Dup(); break;

                //-------------------------
                //4.5: Storage Operators
                case OperatorName.put: evalStack.Put(); break;

                case OperatorName.get: evalStack.Get(); break;

                //-------------------------
                //4.6: Conditional
                case OperatorName.and: evalStack.Op_And(); break;

                case OperatorName.or: evalStack.Op_Or(); break;

                case OperatorName.not: evalStack.Op_Not(); break;

                case OperatorName.eq: evalStack.Op_Eq(); break;

                case OperatorName.ifelse: evalStack.Op_IfElse(); break;

                //
                case OperatorName.rlineto: evalStack.R_LineTo(); break;

                case OperatorName.hlineto: evalStack.H_LineTo(); break;

                case OperatorName.vlineto: evalStack.V_LineTo(); break;

                case OperatorName.rrcurveto: evalStack.RR_CurveTo(); break;

                case OperatorName.hhcurveto: evalStack.HH_CurveTo(); break;

                case OperatorName.hvcurveto: evalStack.HV_CurveTo(); break;

                case OperatorName.rcurveline: evalStack.R_CurveLine(); break;

                case OperatorName.rlinecurve: evalStack.R_LineCurve(); break;

                case OperatorName.vhcurveto: evalStack.VH_CurveTo(); break;

                case OperatorName.vvcurveto: evalStack.VV_CurveTo(); break;

                //-------------------------------------------------------------------
                case OperatorName.rmoveto: evalStack.R_MoveTo(); break;

                case OperatorName.hmoveto: evalStack.H_MoveTo(); break;

                case OperatorName.vmoveto: evalStack.V_MoveTo(); break;

                //-------------------------------------------------------------------
                //4.3 Hint Operators
                case OperatorName.hstem: evalStack.H_Stem(); break;

                case OperatorName.vstem: evalStack.V_Stem(); break;

                case OperatorName.vstemhm: evalStack.V_StemHM(); break;

                case OperatorName.hstemhm: evalStack.H_StemHM(); break;

                //--------------------------
                case OperatorName.hintmask1: evalStack.HintMask1(inst.Value); break;

                case OperatorName.hintmask2: evalStack.HintMask2(inst.Value); break;

                case OperatorName.hintmask3: evalStack.HintMask3(inst.Value); break;

                case OperatorName.hintmask4: evalStack.HintMask4(inst.Value); break;

                case OperatorName.hintmask_bits: evalStack.HintMaskBits(inst.Value); break;

                //------------------------------
                case OperatorName.cntrmask1: evalStack.CounterSpaceMask1(inst.Value); break;

                case OperatorName.cntrmask2: evalStack.CounterSpaceMask2(inst.Value); break;

                case OperatorName.cntrmask3: evalStack.CounterSpaceMask3(inst.Value); break;

                case OperatorName.cntrmask4: evalStack.CounterSpaceMask4(inst.Value); break;

                case OperatorName.cntrmask_bits: evalStack.CounterSpaceMaskBits(inst.Value); break;

                //-------------------------
                //4.7: Subroutine Operators
                case OperatorName._return:
                {
                    //***
                    //don't forget to return _evalStack's currentX, currentY to prev evl context
                    currentX = evalStack._currentX;
                    currentY = evalStack._currentY;
                    evalStack.Ret();
                }
                break;

                case OperatorName.callsubr:
                {
                    //resolve local subrountine
                    int rawSubRoutineNum = (int)evalStack.Pop();
                    Type2GlyphInstructionList resolvedSubroutine = _cff1Font._localSubrs[rawSubRoutineNum + _cffBias];
                    //then we move to another context
                    //recursive ***
                    Run(tx, resolvedSubroutine, ref evalStack._currentX, ref evalStack._currentY);
                }
                break;

                case OperatorName.callgsubr: throw new NotSupportedException();
                }
            }


            ReleaseEvalStack(evalStack);//****
        }
Exemple #3
0
        public Type2GlyphInstructionList ParseType2CharString(byte[] buffer)
        {
            //reset
            current_int_count = 0;
            foundSomeStem     = false;
            doStemCount       = true;
            _msBuffer.SetLength(0);
            _msBuffer.Position = 0;
            _msBuffer.Write(buffer, 0, buffer.Length);
            _msBuffer.Position = 0;
            int len = buffer.Length;

            //
            insts = new Type2GlyphInstructionList();
#if DEBUG
            insts.dbugMark = _dbugInstructionListMark;
            //if (_dbugInstructionListMark == 5)
            //{

            //}
            _dbugInstructionListMark++;
#endif

            byte b0            = 0;
            int  hintStemCount = 0;

            bool cont = true;

            while (cont && _reader.BaseStream.Position < len)
            {
                b0 = _reader.ReadByte();
#if DEBUG
                //easy for debugging here
                _dbugCount++;
                if (b0 < 32)
                {
                }
#endif
                switch (b0)
                {
                default:     //else 32 -255
                {
                    if (b0 < 32)
                    {
                        Debug.WriteLine("err!:" + b0);
                        return(null);
                    }
                    insts.AddInt(ReadIntegerNumber(b0));
                    if (doStemCount)
                    {
                        current_int_count++;
                    }
                }
                break;

                case (byte)Type2Operator1.shortint:     // 28

                    //shortint
                    //First byte of a 3-byte sequence specifying a number.
                    //a ShortInt value is specified by using the operator (28) followed by two bytes
                    //which represent numbers between –32768 and + 32767.The
                    //most significant byte follows the(28)
                    byte s_b0 = _reader.ReadByte();
                    byte s_b1 = _reader.ReadByte();
                    insts.AddInt((short)((s_b0 << 8) | (s_b1)));
                    //
                    if (doStemCount)
                    {
                        current_int_count++;
                    }
                    break;

                //---------------------------------------------------
                case (byte)Type2Operator1._Reserved0_:    //???
                case (byte)Type2Operator1._Reserved2_:    //???
                case (byte)Type2Operator1._Reserved9_:    //???
                case (byte)Type2Operator1._Reserved13_:   //???
                case (byte)Type2Operator1._Reserved15_:   //???
                case (byte)Type2Operator1._Reserved16_:   //???
                case (byte)Type2Operator1._Reserved17_:   //???
                    //reserved, do nothing ?
                    break;

                case (byte)Type2Operator1.endchar:
                    insts.AddOp(OperatorName.endchar);
                    cont = false;
                    //when we found end char
                    //stop reading this...
                    break;

                case (byte)Type2Operator1.escape:     //12
                {
                    b0 = _reader.ReadByte();
                    switch ((Type2Operator2)b0)
                    {
                    default:
                        if (b0 <= 38)
                        {
                            Debug.WriteLine("err!:" + b0);
                            return(null);
                        }
                        break;

                    //-------------------------
                    //4.1: Path Construction Operators
                    case Type2Operator2.flex: insts.AddOp(OperatorName.flex); break;

                    case Type2Operator2.hflex: insts.AddOp(OperatorName.hflex); break;

                    case Type2Operator2.hflex1: insts.AddOp(OperatorName.hflex1); break;

                    case Type2Operator2.flex1: insts.AddOp(OperatorName.flex1);; break;

                    //-------------------------
                    //4.4: Arithmetic Operators
                    case Type2Operator2.abs: insts.AddOp(OperatorName.abs); break;

                    case Type2Operator2.add: insts.AddOp(OperatorName.add); break;

                    case Type2Operator2.sub: insts.AddOp(OperatorName.sub); break;

                    case Type2Operator2.div: insts.AddOp(OperatorName.div); break;

                    case Type2Operator2.neg: insts.AddOp(OperatorName.neg); break;

                    case Type2Operator2.random: insts.AddOp(OperatorName.random); break;

                    case Type2Operator2.mul: insts.AddOp(OperatorName.mul); break;

                    case Type2Operator2.sqrt: insts.AddOp(OperatorName.sqrt); break;

                    case Type2Operator2.drop: insts.AddOp(OperatorName.drop); break;

                    case Type2Operator2.exch: insts.AddOp(OperatorName.exch); break;

                    case Type2Operator2.index: insts.AddOp(OperatorName.index); break;

                    case Type2Operator2.roll: insts.AddOp(OperatorName.roll); break;

                    case Type2Operator2.dup: insts.AddOp(OperatorName.dup); break;

                    //-------------------------
                    //4.5: Storage Operators
                    case Type2Operator2.put: insts.AddOp(OperatorName.put); break;

                    case Type2Operator2.get: insts.AddOp(OperatorName.get); break;

                    //-------------------------
                    //4.6: Conditional
                    case Type2Operator2.and: insts.AddOp(OperatorName.and); break;

                    case Type2Operator2.or: insts.AddOp(OperatorName.or); break;

                    case Type2Operator2.not: insts.AddOp(OperatorName.not); break;

                    case Type2Operator2.eq: insts.AddOp(OperatorName.eq); break;

                    case Type2Operator2.ifelse: insts.AddOp(OperatorName.ifelse); break;
                    }

                    StopStemCount();
                }
                break;

                case (byte)Type2Operator1.rmoveto: insts.AddOp(OperatorName.rmoveto); StopStemCount(); break;

                case (byte)Type2Operator1.hmoveto: insts.AddOp(OperatorName.hmoveto); StopStemCount(); break;

                case (byte)Type2Operator1.vmoveto: insts.AddOp(OperatorName.vmoveto); StopStemCount(); break;

                //---------------------------------------------------------------------------
                case (byte)Type2Operator1.rlineto: insts.AddOp(OperatorName.rlineto); StopStemCount(); break;

                case (byte)Type2Operator1.hlineto: insts.AddOp(OperatorName.hlineto); StopStemCount(); break;

                case (byte)Type2Operator1.vlineto: insts.AddOp(OperatorName.vlineto); StopStemCount(); break;

                case (byte)Type2Operator1.rrcurveto: insts.AddOp(OperatorName.rrcurveto); StopStemCount(); break;

                case (byte)Type2Operator1.hhcurveto: insts.AddOp(OperatorName.hhcurveto); StopStemCount(); break;

                case (byte)Type2Operator1.hvcurveto: insts.AddOp(OperatorName.hvcurveto); StopStemCount(); break;

                case (byte)Type2Operator1.rcurveline: insts.AddOp(OperatorName.rcurveline); StopStemCount(); break;

                case (byte)Type2Operator1.rlinecurve: insts.AddOp(OperatorName.rlinecurve); StopStemCount(); break;

                case (byte)Type2Operator1.vhcurveto: insts.AddOp(OperatorName.vhcurveto); StopStemCount(); break;

                case (byte)Type2Operator1.vvcurveto: insts.AddOp(OperatorName.vvcurveto); StopStemCount(); break;

                //-------------------------------------------------------------------
                //4.3 Hint Operators
                case (byte)Type2Operator1.hstem: AddStemToList(OperatorName.hstem, ref hintStemCount); break;

                case (byte)Type2Operator1.vstem: AddStemToList(OperatorName.vstem, ref hintStemCount); break;

                case (byte)Type2Operator1.vstemhm: AddStemToList(OperatorName.vstemhm, ref hintStemCount); break;

                case (byte)Type2Operator1.hstemhm: AddStemToList(OperatorName.hstemhm, ref hintStemCount); break;

                //-------------------------------------------------------------------
                case (byte)Type2Operator1.hintmask: AddHintMaskToList(_reader, ref hintStemCount); StopStemCount(); break;

                case (byte)Type2Operator1.cntrmask: AddCounterMaskToList(_reader, ref hintStemCount); StopStemCount(); break;

                //-------------------------------------------------------------------
                //4.7: Subroutine Operators
                case (byte)Type2Operator1.callsubr: insts.AddOp(OperatorName.callsubr); StopStemCount(); break;

                case (byte)Type2Operator1.callgsubr: insts.AddOp(OperatorName.callgsubr); StopStemCount(); break;

                case (byte)Type2Operator1._return: insts.AddOp(OperatorName._return); StopStemCount(); break;
                }
            }
            return(insts);
        }