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);//**** }
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); }