public Type2Instruction RemoveLast()
        {
            int last = _insts.Count - 1;
            Type2Instruction _lastInst = _insts[last];

            _insts.RemoveAt(last);
            return(_lastInst);
        }
        void dbugReExpandAndCompare_ForStep1(List <Type2Instruction> step1, List <Type2Instruction> org)
        {
            List <Type2Instruction> expand1 = new List <Type2Instruction>(org.Count);

            {
                int j = step1.Count;
                for (int i = 0; i < j; ++i)
                {
                    Type2Instruction inst = step1[i];
                    switch ((OperatorName)inst.Op)
                    {
                    case OperatorName.LoadSbyte4:
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 24)));
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 16)));
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 8)));
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value)));
                        break;

                    case OperatorName.LoadSbyte3:
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 24)));
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 16)));
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 8)));
                        break;

                    case OperatorName.LoadShort2:
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (short)(inst.Value >> 16)));
                        expand1.Add(new Type2Instruction(OperatorName.LoadInt, (short)(inst.Value)));
                        break;

                    default:
                        expand1.Add(inst);
                        break;
                    }
                }
            }
            //--------------------------------------------
            if (expand1.Count != org.Count)
            {
                throw new NotSupportedException();
            }
            else
            {
                //compare command-by-command
                int j = step1.Count;
                for (int i = 0; i < j; ++i)
                {
                    Type2Instruction inst_exp = expand1[i];
                    Type2Instruction inst_org = org[i];
                    if (inst_exp.Op != inst_org.Op ||
                        inst_exp.Value != inst_org.Value)
                    {
                        throw new NotSupportedException();
                    }
                }
            }
        }
        internal void ChangeFirstInstToGlyphWidthValue()
        {
            //check the first element must be loadint
            Type2Instruction firstInst = _insts[0];

            if (!firstInst.IsLoadInt)
            {
                throw new NotSupportedException();
            }
            //the replace
            _insts[0] = new Type2Instruction(OperatorName.GlyphWidth, firstInst.Value);
        }
Example #4
0
        internal void dbugDumpInstructionListToFile(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Create))
                using (StreamWriter w = new StreamWriter(fs))
                {
                    int j = insts.Count;
                    for (int i = 0; i < j; ++i)
                    {
                        Type2Instruction inst = insts[i];

                        w.Write("[" + i + "] ");
                        if (inst.Op == OperatorName.LoadInt)
                        {
                            w.Write(inst.Value.ToString());
                            w.Write(' ');
                        }
                        else
                        {
                            w.Write(inst.ToString());
                            w.WriteLine();
                        }
                    }
                }
        }
        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);//****
        }
        void dbugReExpandAndCompare_ForStep2(List <Type2Instruction> step2, List <Type2Instruction> org)
        {
            List <Type2Instruction> expand2 = new List <Type2Instruction>(org.Count);

            {
                int j = step2.Count;
                for (int i = 0; i < j; ++i)
                {
                    Type2Instruction inst = step2[i];

                    //we use upper 2 bits to indicate that this is merged cmd or not
                    byte merge_flags = (byte)(inst.Op >> 6);
                    //lower 6 bits is actual cmd
                    OperatorName onlyOpName = (OperatorName)(inst.Op & 0b111111);
                    switch (onlyOpName)
                    {
                    case OperatorName.LoadSbyte4:
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 24)));
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 16)));
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 8)));
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value)));
                        break;

                    case OperatorName.LoadSbyte3:
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 24)));
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 16)));
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 8)));
                        break;

                    case OperatorName.LoadShort2:
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (short)(inst.Value >> 16)));
                        expand2.Add(new Type2Instruction(OperatorName.LoadInt, (short)(inst.Value)));
                        break;

                    default:
                    {
                        switch (merge_flags)
                        {
                        case 0:
                            expand2.Add(inst);
                            break;

                        case 1:
                            expand2.Add(new Type2Instruction(OperatorName.LoadInt, inst.Value));
                            expand2.Add(new Type2Instruction(onlyOpName, 0));
                            break;

                        case 2:
                            expand2.Add(new Type2Instruction(OperatorName.LoadInt, (short)(inst.Value >> 16)));
                            expand2.Add(new Type2Instruction(OperatorName.LoadInt, (short)(inst.Value)));
                            expand2.Add(new Type2Instruction(onlyOpName, 0));
                            break;

                        case 3:
                            expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 24)));
                            expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 16)));
                            expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value >> 8)));
                            expand2.Add(new Type2Instruction(OperatorName.LoadInt, (sbyte)(inst.Value)));
                            expand2.Add(new Type2Instruction(onlyOpName, 0));
                            break;
                        }
                    }
                    break;
                    }
                }
            }
            //--------------------------------------------
            if (expand2.Count != org.Count)
            {
                throw new NotSupportedException();
            }
            else
            {
                //compare command-by-command
                int j = step2.Count;
                for (int i = 0; i < j; ++i)
                {
                    Type2Instruction inst_exp = expand2[i];
                    Type2Instruction inst_org = org[i];
                    if (inst_exp.Op != inst_org.Op ||
                        inst_exp.Value != inst_org.Value)
                    {
                        throw new NotSupportedException();
                    }
                }
            }
        }
        void CompactStep2MergeLoadIntWithNextCommand()
        {
            //a second pass
            //check if we can merge some load int( LoadInt, LoadSByte4, LoadShort2) except LoadSByte3
            //to next instruction command or not
            int j = _step1List.Count;

            for (int i = 0; i < j; ++i)
            {
                Type2Instruction i0 = _step1List[i];

                if (i + 1 < j)
                {
                    //has next cmd
                    byte merge_flags = IsLoadIntOrMergeableLoadIntExtension((OperatorName)i0.Op);
                    if (merge_flags > 0)
                    {
                        Type2Instruction i1 = _step1List[i + 1];
                        //check i1 has empty space for i0 or not
                        bool canbe_merged = false;
                        switch ((OperatorName)i1.Op)
                        {
                        case OperatorName.LoadInt:
                        case OperatorName.LoadShort2:
                        case OperatorName.LoadSbyte4:
                        case OperatorName.LoadSbyte3:
                        case OperatorName.LoadFloat:

                        case OperatorName.hintmask1:
                        case OperatorName.hintmask2:
                        case OperatorName.hintmask3:
                        case OperatorName.hintmask4:
                        case OperatorName.hintmask_bits:
                        case OperatorName.cntrmask1:
                        case OperatorName.cntrmask2:
                        case OperatorName.cntrmask3:
                        case OperatorName.cntrmask4:
                        case OperatorName.cntrmask_bits:
                            break;

                        default:
                            canbe_merged = true;
                            break;
                        }
                        if (canbe_merged)
                        {
#if DEBUG
                            if (merge_flags > 3)
                            {
                                throw new NotSupportedException();
                            }
#endif

                            _step2List.Add(new Type2Instruction((byte)((merge_flags << 6) | i1.Op), i0.Value));
                            i += 1;
                        }
                        else
                        {
                            _step2List.Add(i0);
                        }
                    }
                    else
                    {
                        //this is the last one
                        _step2List.Add(i0);
                    }
                }
                else
                {
                    //this is the last one
                    _step2List.Add(i0);
                }
            }
        }
        void CompactStep1OnlyLoadInt(List <Type2Instruction> insts)
        {
            int          j = insts.Count;
            CompactRange _latestCompactRange = CompactRange.None;
            int          startCollectAt      = -1;
            int          collecting_count    = 0;

            void FlushWaitingNumbers()
            {
                //Nested method
                //flush waiting integer
                if (_latestCompactRange == CompactRange.Short)
                {
                    switch (collecting_count)
                    {
                    default: throw new NotSupportedException();

                    case 0: break;     //nothing

                    case 2:
                        _step1List.Add(new Type2Instruction(OperatorName.LoadShort2,
                                                            (((ushort)insts[startCollectAt].Value) << 16) |
                                                            (((ushort)insts[startCollectAt + 1].Value))
                                                            ));
                        startCollectAt   += 2;
                        collecting_count -= 2;
                        break;

                    case 1:
                        _step1List.Add(insts[startCollectAt]);
                        startCollectAt   += 1;
                        collecting_count -= 1;
                        break;
                    }
                }
                else
                {
                    switch (collecting_count)
                    {
                    default: throw new NotSupportedException();

                    case 0: break;    //nothing

                    case 4:
                    {
                        _step1List.Add(new Type2Instruction(OperatorName.LoadSbyte4,
                                                            (((byte)insts[startCollectAt].Value) << 24) |
                                                            (((byte)insts[startCollectAt + 1].Value) << 16) |
                                                            (((byte)insts[startCollectAt + 2].Value) << 8) |
                                                            (((byte)insts[startCollectAt + 3].Value) << 0)
                                                            ));
                        startCollectAt   += 4;
                        collecting_count -= 4;
                    }
                    break;

                    case 3:
                        _step1List.Add(new Type2Instruction(OperatorName.LoadSbyte3,
                                                            (((byte)insts[startCollectAt].Value) << 24) |
                                                            (((byte)insts[startCollectAt + 1].Value) << 16) |
                                                            (((byte)insts[startCollectAt + 2].Value) << 8)
                                                            ));
                        startCollectAt   += 3;
                        collecting_count -= 3;
                        break;

                    case 2:
                        _step1List.Add(new Type2Instruction(OperatorName.LoadShort2,
                                                            (((ushort)insts[startCollectAt].Value) << 16) |
                                                            ((ushort)insts[startCollectAt + 1].Value)
                                                            ));
                        startCollectAt   += 2;
                        collecting_count -= 2;
                        break;

                    case 1:
                        _step1List.Add(insts[startCollectAt]);
                        startCollectAt   += 1;
                        collecting_count -= 1;
                        break;
                    }
                }

                startCollectAt   = -1;
                collecting_count = 0;
            }

            for (int i = 0; i < j; ++i)
            {
                Type2Instruction inst = insts[i];
                if (inst.IsLoadInt)
                {
                    //check waiting data in queue
                    //get compact range
                    CompactRange c1 = GetCompactRange(inst.Value);
                    switch (c1)
                    {
                    default: throw new NotSupportedException();

                    case CompactRange.None:
                    {
                    }
                    break;

                    case CompactRange.SByte:
                    {
                        if (_latestCompactRange == CompactRange.Short)
                        {
                            FlushWaitingNumbers();
                            _latestCompactRange = CompactRange.SByte;
                        }

                        switch (collecting_count)
                        {
                        default: throw new NotSupportedException();

                        case 0:
                            startCollectAt      = i;
                            _latestCompactRange = CompactRange.SByte;
                            break;

                        case 1:
                            break;

                        case 2:
                            break;

                        case 3:
                            //we already have 3 bytes
                            //so this is 4th byte
                            collecting_count++;
                            FlushWaitingNumbers();
                            continue;
                        }
                        collecting_count++;
                    }
                    break;

                    case CompactRange.Short:
                    {
                        if (_latestCompactRange == CompactRange.SByte)
                        {
                            FlushWaitingNumbers();
                            _latestCompactRange = CompactRange.Short;
                        }

                        switch (collecting_count)
                        {
                        default: throw new NotSupportedException();

                        case 0:
                            startCollectAt      = i;
                            _latestCompactRange = CompactRange.Short;
                            break;

                        case 1:
                            //we already have 1 so this is 2nd
                            collecting_count++;
                            FlushWaitingNumbers();
                            continue;
                        }

                        collecting_count++;
                    }
                    break;
                    }
                }
                else
                {
                    //other cmds
                    //flush waiting cmd
                    if (collecting_count > 0)
                    {
                        FlushWaitingNumbers();
                    }

                    _step1List.Add(inst);
                    _latestCompactRange = CompactRange.None;
                }
            }
        }