public void AddContent(byte[] content, SortedDictionary<Int32, PDFobj> objects) { PDFobj obj = new PDFobj(); int maxObjNumber = -1; foreach (int number in objects.Keys) { if (number > maxObjNumber) { maxObjNumber = number; } } obj.SetNumber(maxObjNumber + 1); obj.SetStream(content); objects.Add(obj.GetNumber(), obj); int index = -1; bool single = false; for (int i = 0; i < dict.Count; i++) { if (dict[i].Equals("/Contents")) { String str = dict[++i]; if (str.Equals("[")) { for (;;) { str = dict[++i]; if (str.Equals("]")) { index = i; break; } ++i; // 0 ++i; // R } } else { // Single content object index = i; single = true; } break; } } if (single) { dict.Insert(index, "["); dict.Insert(index + 4, "]"); dict.Insert(index + 4, "R"); dict.Insert(index + 4, "0"); dict.Insert(index + 4, obj.number.ToString()); } else { dict.Insert(index, "R"); dict.Insert(index, "0"); dict.Insert(index, obj.number.ToString()); } }
public void AddObjects(SortedDictionary<Int32, PDFobj> objects) { foreach (PDFobj obj in objects.Values) { if (obj.GetValue("/Type").Equals("/Pages") && obj.GetValue("/Parent").Equals("")) { this.pagesObjNumber = Int32.Parse(obj.dict[0]); } } int maxObjNumber = -1; foreach (int number in objects.Keys) { if (number > maxObjNumber) { maxObjNumber = number; } } for (int i = 1; i < maxObjNumber; i++) { if (!objects.ContainsKey(i)) { PDFobj obj = new PDFobj(); obj.number = i; objects.Add(obj.number, obj); } } foreach (PDFobj obj in objects.Values) { objNumber = obj.number; objOffset.Add(byte_count); if (obj.offset == 0) { Append(obj.number); Append(" 0 obj\n"); if (obj.dict != null) { for (int i = 0; i < obj.dict.Count; i++) { Append(obj.dict[i]); Append(' '); } } if (obj.stream != null) { Append("<< /Length "); Append(obj.stream.Length); Append(" >>"); Append("\nstream\n"); for (int i = 0; i < obj.stream.Length; i++) { Append(obj.stream[i]); } Append("\nendstream\n"); } Append("endobj\n"); continue; } int n = obj.dict.Count; String token = null; for (int i = 0; i < n; i++) { token = obj.dict[i]; Append(token); if (i < (n - 1)) { Append(' '); } else { Append('\n'); } } if (obj.stream != null) { for (int i = 0; i < obj.stream.Length; i++) { Append(obj.stream[i]); } Append("\nendstream\n"); } if (!token.Equals("endobj")) { Append("endobj\n"); } } }
private bool Process(PDFobj obj, StringBuilder buf, int off) { String token = buf.ToString().Trim(); if (!token.Equals("")) { obj.dict.Add(token); } buf.Length = 0; if (token.Equals("stream") || token.Equals("endobj") || token.Equals("startxref")) { if (token.Equals("stream")) { if (endOfLine == CR_LF) { obj.stream_offset = off + 1; } else if (endOfLine == CR || endOfLine == LF) { obj.stream_offset = off; } } return true; } return false; }
private bool IsPageObject(PDFobj obj) { bool isPage = false; for (int i = 0; i < obj.dict.Count; i++) { if (obj.dict[i].Equals("/Type") && obj.dict[i + 1].Equals("/Page")) { isPage = true; } } return isPage; }
private void GetPageObjects(PDFobj pdfObj, SortedDictionary<Int32, PDFobj> objects, List<PDFobj> pages) { List<Int32> kids = pdfObj.GetObjectNumbers("/Kids"); foreach (Int32 number in kids) { PDFobj obj = objects[number]; if (IsPageObject(obj)) { pages.Add(obj); } else { GetPageObjects(obj, objects, pages); } } }
private void GetObjects2( byte[] pdf, PDFobj obj, List<PDFobj> objects) { String prev = obj.GetValue("/Prev"); if (!prev.Equals("")) { GetObjects2( pdf, GetObject(pdf, Int32.Parse(prev)), objects); } obj.SetStream(pdf, Int32.Parse(obj.GetValue("/Length"))); try { Decompressor decompressor = new Decompressor(obj.stream); obj.data = decompressor.GetDecompressedData(); } catch (Exception e) { // Assume no compression. obj.data = obj.stream; } int p1 = 0; // Predictor byte int f1 = 0; // Field 1 int f2 = 0; // Field 2 int f3 = 0; // Field 3 for (int i = 0; i < obj.dict.Count; i++) { String token = obj.dict[i]; if (token.Equals("/Predictor")) { if (obj.dict[i + 1].Equals("12")) { p1 = 1; } } if (token.Equals("/W")) { // "/W [ 1 3 1 ]" f1 = Int32.Parse(obj.dict[i + 2]); f2 = Int32.Parse(obj.dict[i + 3]); f3 = Int32.Parse(obj.dict[i + 4]); } } int n = p1 + f1 + f2 + f3; // Number of bytes per entry byte[] entry = new byte[n]; for (int i = 0; i < obj.data.Length; i += n) { // Apply the 'Up' filter. for (int j = 0; j < n; j++) { entry[j] += obj.data[i + j]; } // Process the entries in a cross-reference stream // Page 51 in PDF32000_2008.pdf if (entry[p1] == 1) { // Type 1 entry PDFobj o2 = GetObject(pdf, ToInt(entry, p1 + f1, f2)); o2.number = Int32.Parse(o2.dict[0]); objects.Add(o2); } } }
private void GetObjects1( byte[] pdf, PDFobj obj, List<PDFobj> objects) { String xref = obj.GetValue("/Prev"); if (!xref.Equals("")) { GetObjects1( pdf, GetObject(pdf, Int32.Parse(xref)), objects); } int i = 1; while (true) { String token = obj.dict[i++]; if (token.Equals("trailer")) { break; } int n = Int32.Parse(obj.dict[i++]); // Number of entries for (int j = 0; j < n; j++) { String offset = obj.dict[i++]; // Object offset String number = obj.dict[i++]; // Generation number String status = obj.dict[i++]; // Status keyword if (!status.Equals("f")) { PDFobj o2 = GetObject(pdf, Int32.Parse(offset)); o2.number = Int32.Parse(o2.dict[0]); objects.Add(o2); } } } }
private PDFobj GetObject(byte[] buf, int off, int len) { PDFobj obj = new PDFobj(off); StringBuilder token = new StringBuilder(); int p = 0; char c1 = ' '; bool done = false; while (!done && off < len) { char c2 = (char) buf[off++]; if (c2 == '(') { if (p == 0) { done = Process(obj, token, off); } if (!done) { token.Append(c2); ++p; } } else if (c2 == ')') { token.Append(c2); --p; if (p == 0) { done = Process(obj, token, off); } } else if (c2 == 0x00 // Null || c2 == 0x09 // Horizontal Tab || c2 == 0x0A // Line Feed (LF) || c2 == 0x0C // Form Feed || c2 == 0x0D // Carriage Return (CR) || c2 == 0x20) { // Space done = Process(obj, token, off); if (!done) { c1 = ' '; } } else if (c2 == '/') { done = Process(obj, token, off); if (!done) { token.Append(c2); c1 = c2; } } else if (c2 == '<' || c2 == '>' || c2 == '%') { if (c2 != c1) { done = Process(obj, token, off); if (!done) { token.Append(c2); c1 = c2; } } else { token.Append(c2); done = Process(obj, token, off); if (!done) { c1 = ' '; } } } else if (c2 == '[' || c2 == ']' || c2 == '{' || c2 == '}') { done = Process(obj, token, off); if (!done) { obj.dict.Add(c2.ToString()); c1 = c2; } } else { token.Append(c2); if (p == 0) { c1 = c2; } } } return obj; }
private void AddFontResource( PDFobj obj, SortedDictionary<Int32, PDFobj> objects, String fontID, int number) { for (int i = 0; i < obj.dict.Count; i++) { String token = null; if (obj.dict[i].Equals("/Font")) { token = obj.dict[++i]; if (token.Equals("<<")) { obj.dict.Insert(++i, "/" + fontID); obj.dict.Insert(++i, number.ToString()); obj.dict.Insert(++i, "0"); obj.dict.Insert(++i, "R"); break; } else if (Char.IsDigit(token[0])) { PDFobj o2 = objects[Int32.Parse(token)]; for (int j = 0; j < o2.dict.Count; j++) { token = o2.dict[j]; if (token.Equals("<<")) { o2.dict.Insert(++j, "/" + fontID); o2.dict.Insert(++j, number.ToString()); o2.dict.Insert(++j, "0"); o2.dict.Insert(++j, "R"); break; } } } } } }
public Font AddFontResource(CoreFont coreFont, SortedDictionary<Int32, PDFobj> objects) { Font font = new Font(coreFont); font.fontID = font.name.Replace('-', '_').ToUpper(); PDFobj obj = new PDFobj(); int maxObjNumber = -1; foreach (int number in objects.Keys) { if (number > maxObjNumber) { maxObjNumber = number; } } obj.number = maxObjNumber + 1; obj.dict.Add("<<"); obj.dict.Add("/Type"); obj.dict.Add("/Font"); obj.dict.Add("/Subtype"); obj.dict.Add("/Type1"); obj.dict.Add("/BaseFont"); obj.dict.Add("/" + font.name); if (!font.name.Equals("Symbol") && !font.name.Equals("ZapfDingbats")) { obj.dict.Add("/Encoding"); obj.dict.Add("/WinAnsiEncoding"); } obj.dict.Add(">>"); objects.Add(obj.number, obj); for (int i = 0; i < dict.Count; i++) { if (dict[i].Equals("/Resources")) { String token = dict[++i]; if (token.Equals("<<")) { // Direct resources object AddFontResource(this, objects, font.fontID, obj.number); } else if (Char.IsDigit(token[0])) { // Indirect resources object AddFontResource(objects[Int32.Parse(token)], objects, font.fontID, obj.number); } } } return font; }
public Image(PDF pdf, PDFobj obj) { pdf.newobj(); pdf.Append("<<\n"); pdf.Append("/Type /XObject\n"); pdf.Append("/Subtype /Image\n"); pdf.Append("/Filter "); pdf.Append(obj.getValue(PDFobj.FILTER)); pdf.Append('\n'); pdf.Append("/Width "); pdf.Append(obj.getValue(PDFobj.WIDTH)); pdf.Append('\n'); pdf.Append("/Height "); pdf.Append(obj.getValue(PDFobj.HEIGHT)); pdf.Append('\n'); pdf.Append("/ColorSpace "); pdf.Append(obj.getValue(PDFobj.COLORSPACE)); pdf.Append('\n'); pdf.Append("/BitsPerComponent "); pdf.Append(obj.getValue(PDFobj.BITSPERCOMPONENT)); pdf.Append('\n'); pdf.Append("/Length "); pdf.Append(obj.stream.Length); pdf.Append('\n'); pdf.Append(">>\n"); pdf.Append("stream\n"); pdf.Append(obj.stream, 0, obj.stream.Length); pdf.Append("\nendstream\n"); pdf.endobj(); pdf.images.Add(this); objNumber = pdf.objNumber; }
private PDFobj getObject( byte[] buf, int off, int end ) { PDFobj obj = new PDFobj( off ); StringBuilder sb = new StringBuilder(); int n = 0; char c1 = ' '; while ( true ) { if ( off == end ) { Append( obj, sb, off ); break; } char c2 = (char) buf[off++]; if ( c2 == '(' ) { if ( n == 0 ) { if ( !Append( obj, sb, off ) ) break; } sb.Append( c2 ); ++n; } else if ( c2 == ')' ) { sb.Append( c2 ); --n; if ( n == 0 ) { if ( !Append( obj, sb, off ) ) break; } } else if ( n > 0 ) { sb.Append( c2 ); } else if ( c2 == 0x00 // Null || c2 == 0x09 // Horizontal Tab || c2 == 0x0A // Line Feed (LF) || c2 == 0x0C // Form Feed || c2 == 0x0D // Carriage Return (CR) || c2 == 0x20 ) { // Space if ( !Append( obj, sb, off ) ) break; c1 = ' '; } else if ( c2 == '/' ) { if ( !Append( obj, sb, off ) ) break; sb.Append( c2 ); c1 = c2; } else if ( c2 == '<' || c2 == '>' ) { if ( c2 != c1 ) { if ( !Append( obj, sb, off ) ) break; sb.Append( c2 ); c1 = c2; } else { sb.Append( c2 ); if ( !Append( obj, sb, off ) ) break; c1 = ' '; } } else if ( c2 == '[' || c2 == ']' ) { if ( !Append( obj, sb, off ) ) break; obj.dict.Add( c2.ToString() ); c1 = c2; } else if ( c2 == '{' || c2 == '}' ) { if ( !Append( obj, sb, off ) ) break; obj.dict.Add( c2.ToString() ); c1 = c2; } else if ( c2 == '%' ) { if ( c2 != c1 ) { if ( !Append( obj, sb, off ) ) break; sb.Append( c2 ); c1 = c2; } else { sb.Append( c2 ); if ( !Append( obj, sb, off ) ) break; c1 = ' '; } } else { sb.Append( c2 ); c1 = c2; } } return obj; }
private bool Append(PDFobj obj, StringBuilder sb, int offset) { String token = sb.ToString().Trim(); if ( !token.Equals( "" ) ) { obj.dict.Add( token ); } sb.Length = 0; if ( token.Equals( "stream" ) || token.Equals( "endobj" ) || token.Equals( "trailer" ) ) { if ( token.Equals( "stream" ) ) { if ( CR_LF ) { obj.stream_offset = offset + 1; } else { obj.stream_offset = offset; } } return false; } return true; }