protected T ReadDictionary(T dictionary, CompactFontFormatData data, string[] stringIndex) { while (data.CanRead()) { operands.Clear(); var infiniteLoopProtection = 0; while (true) { infiniteLoopProtection++; // Avoid the library getting caught in an infinite loop, probably not possible. // "An operator may be preceded by up to a maximum of 48 operands." if (infiniteLoopProtection > 256) { throw new InvalidOperationException("Got caught in an infinite loop trying to read a CFF dictionary."); } var byte0 = data.ReadByte(); // Operands and operators are distinguished by the first byte, 0 - 21 specify operators if (byte0 <= 21) { var key = byte0 == 12 ? new OperandKey(byte0, data.ReadByte()) : new OperandKey(byte0); ApplyOperation(dictionary, operands, key, stringIndex); break; } /* * b0 value value range calculation * 32 - 246 -107 - +107 b0 - 139 * 247 - 250 +108 - +1131 (b0 - 247)*256 + b1 + 108 * 251 - 254 -1131 - -108 -(b0 - 251)*256 - b1 - 108 * 28 -32768 - +32767 b1 << 8 | b2 * 29 -(2^31)-+(2^31-1) b1 << 24 | b2 << 16 | b3 << 8 | b4 * * A byte value of 30 defines a real number operand */ if (byte0 == 28) { var value = data.ReadByte() << 8 | data.ReadByte(); operands.Add(new Operand(value)); } else if (byte0 == 29) { var value = data.ReadByte() << 24 | data.ReadByte() << 16 | data.ReadByte() << 8 | data.ReadByte(); operands.Add(new Operand(value)); } else if (byte0 == 30) { var realNumber = ReadRealNumber(data); operands.Add(new Operand(realNumber)); } else if (byte0 >= 32 && byte0 <= 246) { var value = byte0 - 139; operands.Add(new Operand(value)); } else if (byte0 >= 247 && byte0 <= 250) { var value = (byte0 - 247) * 256 + data.ReadByte() + 108; operands.Add(new Operand(value)); } else if (byte0 >= 251 && byte0 <= 254) { var value = -(byte0 - 251) * 256 - data.ReadByte() - 108; operands.Add(new Operand(value)); } else { throw new InvalidOperationException($"The first dictionary byte was not in the range 29 - 254. Got {byte0}."); } } } return(dictionary); }