Exemple #1
0
        /// <summary>
        /// Append text string
        /// </summary>
        /// <param name="Text"></param>
        public void AppendText
        (
            string Text
        )
        {
            // remove double delimeters
            if (ByteArray.Count > 0 && !PdfBase.IsDelimiter(ByteArray[ByteArray.Count - 1]) && !PdfBase.IsDelimiter(Text[0]))
            {
                ByteArray.Add((byte)' ');
            }

            // move charaters to bytes
            foreach (char Chr in Text)
            {
                ByteArray.Add((byte)Chr);
            }
            return;
        }
Exemple #2
0
        ////////////////////////////////////////////////////////////////////
        // Parse Dictionary
        ////////////////////////////////////////////////////////////////////

        internal PdfDictionary ParseDictionary
        (
            bool InlineImage
        )
        {
            // create empty dictionary
            PdfDictionary Dictionary = new PdfDictionary();

            // read first character after <<
            NextChar = ReadChar();

            // loop until closing >> or EOF
            for (;;)
            {
                // skip white space
                SkipWhiteSpace();

                // end of file
                if (NextChar == EOF)
                {
                    throw new ApplicationException("Invalid dictionary (end of contents)");
                }

                // next character must be / for name
                if (NextChar != '/')
                {
                    // end of dictionary
                    if (!InlineImage)
                    {
                        if (NextChar == '>' && ReadChar() == '>')
                        {
                            break;
                        }
                    }
                    // inline image
                    else
                    {
                        if (NextChar == 'I' && ReadChar() == 'D')
                        {
                            break;
                        }
                    }
                    throw new ApplicationException("Invalid dictionary (name entry must have /)");
                }

                // read name
                StringBuilder Name = new StringBuilder();
                Name.Append((char)NextChar);

                // add more characters until next delimiter
                while ((NextChar = ReadChar()) != EOF && !PdfBase.IsDelimiter(NextChar))
                {
                    Name.Append((char)NextChar);
                }

                // read next item
                PdfBase Value = ParseNextItem();

                // end of file
                if (Value.IsEmpty)
                {
                    throw new ApplicationException("Invalid dictionary (end of contents)");
                }

                // add to result dictionary
                Dictionary.AddKeyValue(Name.ToString(), Value);
            }

            // read next character after >> or ID
            NextChar = ReadChar();

            // exit
            return(Dictionary);
        }
Exemple #3
0
        ////////////////////////////////////////////////////////////////////
        // Test for reference
        // We have positive integer already. Test for zero and R
        ////////////////////////////////////////////////////////////////////

        internal bool TestReference()
        {
            // save current file position
            int Pos = GetPos();

            // save next character
            int TempChar = NextChar;

            for (;;)
            {
                // next character must be space
                if (!PdfBase.IsWhiteSpace(TempChar))
                {
                    break;
                }

                // skip additional white space
                while ((TempChar = ReadChar()) != EOF && PdfBase.IsWhiteSpace(TempChar))
                {
                    ;
                }

                // generation is not supported
                // next character must be zero
                if (TempChar != '0')
                {
                    break;
                }

                // next character must be white space
                TempChar = ReadChar();
                if (!PdfBase.IsWhiteSpace(TempChar))
                {
                    break;
                }

                // skip additional white space
                while ((TempChar = ReadChar()) != EOF && PdfBase.IsWhiteSpace(TempChar))
                {
                    ;
                }

                // next character must be R
                if (TempChar != 'R')
                {
                    break;
                }

                // next character must be a delimiter
                TempChar = ReadChar();
                if (!PdfBase.IsDelimiter(TempChar))
                {
                    break;
                }

                // found
                NextChar = TempChar;
                return(true);
            }

            // restore position
            SetPos(Pos);
            return(false);
        }
Exemple #4
0
        /// <summary>
        /// Parse object reference number n 0 R obj
        /// </summary>
        /// <returns>Object number</returns>
        public int ParseObjectRefNo()
        {
            // loop in case of one or more comments
            SkipComments();

            // must be a digit
            if (NextChar < '0' || NextChar > '9')
            {
                return(0);
            }

            // next content element
            StringBuilder NextItem = new StringBuilder();

            NextItem.Append((char)NextChar);

            // add more characters until next delimiter
            while ((NextChar = ReadChar()) != EOF && !PdfBase.IsDelimiter(NextChar))
            {
                NextItem.Append((char)NextChar);
            }

            // integer
            if (!int.TryParse(NextItem.ToString(), out int ObjNo) || ObjNo <= 0)
            {
                return(0);
            }

            // next character must be space
            if (!PdfBase.IsWhiteSpace(NextChar))
            {
                return(0);
            }

            // skip additional white space
            while ((NextChar = ReadChar()) != EOF && PdfBase.IsWhiteSpace(NextChar))
            {
                ;
            }

            // next character must be zero
            if (NextChar != '0')
            {
                return(0);
            }

            // next character must be white space
            NextChar = ReadChar();
            if (!PdfBase.IsWhiteSpace(NextChar))
            {
                return(0);
            }

            // skip additional white space
            while ((NextChar = ReadChar()) != EOF && PdfBase.IsWhiteSpace(NextChar))
            {
                ;
            }

            // next 3 characters must be obj
            if (NextChar != 'o' || ReadChar() != 'b' || ReadChar() != 'j')
            {
                return(0);
            }

            // next character must be a delimiter
            NextChar = ReadChar();
            if (!PdfBase.IsDelimiter(NextChar))
            {
                return(0);
            }

            // return object number
            return(ObjNo);
        }
Exemple #5
0
        /// <summary>
        /// Parse next item
        /// </summary>
        /// <returns>Derived class from PdfBase</returns>
        public PdfBase ParseNextItem()
        {
            // loop in case of one or more comments
            SkipComments();

            // end of file
            if (NextChar == EOF)
            {
                return(PdfBase.Empty);
            }

            // string
            if (NextChar == '(')
            {
                return(ParseString());
            }

            // array
            if (NextChar == '[')
            {
                return(ParseArray());
            }

            // hex string or dictionary
            if (NextChar == '<')
            {
                // test for dictionary
                if (ReadChar() == '<')
                {
                    return(ParseDictionary(false));
                }

                // move pointer back
                StepBack();

                // hex string
                return(ParseHexString());
            }

            // next content element
            StringBuilder NextItem = new StringBuilder();

            NextItem.Append((char)NextChar);

            // add more characters until next delimiter
            while ((NextChar = ReadChar()) != EOF && !PdfBase.IsDelimiter(NextChar))
            {
                NextItem.Append((char)NextChar);
            }

            // convert next item to string token
            string Token = NextItem.ToString();

            // name
            if (Token[0] == '/')
            {
                // empty name
                if (Token.Length == 1)
                {
                    throw new ApplicationException("Empty name token");
                }

                // exit
                return(new PdfName(Token));
            }

            // integer
            if (int.TryParse(Token, out int IntVal))
            {
                // if parsing non contents streams, an integer can be the start of indirect reference number
                if (!ContentsStream && IntVal > 0 && TestReference())
                {
                    return(new PdfReference(IntVal));
                }

                // integer
                return(new PdfInteger(IntVal));
            }

            // real number with period as decimal separator regardless of region
            if (float.TryParse(Token,
                               NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, NumFormatInfo.PeriodDecSep, out float RealVal))
            {
                // if real number is an integer return PdfInt object
                int TestInt = (int)Math.Truncate(RealVal);
                if (RealVal == (double)TestInt)
                {
                    return(new PdfInteger(TestInt));
                }
                return(new PdfReal(RealVal));
            }

            // false
            if (Token == "false")
            {
                return(new PdfBoolean(false));
            }

            // true
            if (Token == "true")
            {
                return(new PdfBoolean(true));
            }

            // null
            if (Token == "null")
            {
                return(new PdfNull());
            }

            // parse all but contents stream
            if (!ContentsStream)
            {
                // stream special case
                if (Token == "stream")
                {
                    // stream must be foloowed by NL or CR and NL
//					if(NextChar == '\n' || NextChar == '\r' && ReadChar() == '\n') return new PdfKeyword(KeyWord.Stream);
                    if (NextChar == '\n')
                    {
                        return(new PdfKeyword(KeyWord.Stream));
                    }
                    if (NextChar == '\r')
                    {
                        // the PDF spec is very clear that stream must be foloowed by NL or CR and NL
                        // CR by itself is not acceptable
                        if (ReadChar() != '\n')
                        {
                            // HP Scanners Scanned PDF does not conform to PDF standards
                            // https://www.google.com/search?client=firefox-b-d&q=hp+officejet+PDF+scan+files+not+standard
                            // step back to allow re-parsing of the last character
                            StepBack();
                            Reader.InvalidPdfFile = true;
                        }
                        return(new PdfKeyword(KeyWord.Stream));
                    }

                    // error
                    throw new ApplicationException("Stream word must be followed by EOL");
                }

                // endstream
                if (Token == "endstream")
                {
                    return(new PdfKeyword(KeyWord.EndStream));
                }

                // endobj
                if (Token == "endobj")
                {
                    return(new PdfKeyword(KeyWord.EndObj));
                }

                // xref
                if (Token == "xref")
                {
                    return(new PdfKeyword(KeyWord.XRef));
                }

                // xref n
                if (Token == "n")
                {
                    return(new PdfKeyword(KeyWord.N));
                }

                // xref f
                if (Token == "f")
                {
                    return(new PdfKeyword(KeyWord.F));
                }

                // trailer
                if (Token == "trailer")
                {
                    return(new PdfKeyword(KeyWord.Trailer));
                }
            }

            // parse contents stream
            else
            {
                // search for contents operator
                int OpIndex = Array.BinarySearch(OpCtrl.OpCtrlArray, new OpCtrl(Token));

                // not found
                if (OpIndex < 0)
                {
                    throw new ApplicationException("Parsing failed: Unknown contents operator");
                }

                // operator enumeration
                Operator OpCode = OpCtrl.OpCtrlArray[OpIndex].OpCode;

                // inline image
                if (OpCode == Operator.BeginInlineImage)
                {
                    return(ParseInlineImage());
                }

                // PDF operator object
                if (OpCode != Operator.BeginInlineImageData && OpCode != Operator.EndInlineImage)
                {
                    return(new PdfOp(OpCode));
                }
            }

            // error
            throw new ApplicationException("Parsing failed: Unknown token: " + Token);
        }