package uk.co.mmscomputing.imageio.pdf; import java.io.*; import java.util.*; public class PDFCrossReferenceTable implements PDFConstants{ // [1] 43 // one line entry for each indirect object; pointer to location in file // list of cross-reference sections // one section for new file; one section per update // the free entries form a linked list // first entry always obj 0 and gen no 65535 -> head of linked list of free objects // tail of list uses 0 as object number [1] p.44 private PDFCrossReferenceEntry[] entries=null; public PDFCrossReferenceTable(int size){ // read entries=new PDFCrossReferenceEntry[size]; } public PDFCrossReferenceEntry[] getEntries(){ return entries;} private Vector sections = new Vector(); public PDFCrossReferenceTable(){ // write } public void add(PDFCrossReferenceEntry obj){ add(0,0,obj); } public void add(int section, int subsection, PDFCrossReferenceEntry obj){ while(sections.size()<=section){ sections.add(new PDFCrossReferenceSection()); } ((PDFCrossReferenceSection)sections.elementAt(section)).add(subsection,obj); } public int getLastCrossReferenceSectionOffset(){ return ((PDFCrossReferenceSection)sections.lastElement()).getOffset(); } public int size(){ int count=0; Enumeration e = sections.elements(); while(e.hasMoreElements()){ PDFCrossReferenceSection section=(PDFCrossReferenceSection)e.nextElement(); count+=section.size(); } return count; } public void write(PDFFile out)throws IOException{ Enumeration e = sections.elements(); while(e.hasMoreElements()){ PDFCrossReferenceSection section=(PDFCrossReferenceSection)e.nextElement(); section.write(out); } } public PDFCrossReferenceEntry getEntry(int objectNumber){ return entries[objectNumber]; } public void read(PDFScanner s)throws IOException{ int index=0; if(s.symbol==T_XREF){ // at least one cross-reference section do{ // todo: updated files; how does it work ???? PDFCrossReferenceSection section=new PDFCrossReferenceSection(); sections.add(section); index=section.read(s,entries,index); }while(s.symbol==T_XREF); // if cross-reference update sections then read on }else{ throw new IOException(getClass().getName()+".read:\n\tExpect symbol <xref>"); } } static public class PDFCrossReferenceSection{ // one line entry for each indirect object; pointer to location in file // <cross-reference section> ::= // xref // <cross-reference subsection>+ private Vector subsections = new Vector(); private int offset = -1; public int getOffset(){ return offset;} public void add(int subsection, PDFCrossReferenceEntry obj){ while(subsections.size()<=subsection){ subsections.add(new PDFCrossReferenceSubSection()); } ((PDFCrossReferenceSubSection)subsections.elementAt(subsection)).add(obj); } public int size(){ int count=0; Enumeration e = subsections.elements(); while(e.hasMoreElements()){ PDFCrossReferenceSubSection subsection=(PDFCrossReferenceSubSection)e.nextElement(); count+=subsection.size(); } return count; } public int read(PDFScanner s,PDFCrossReferenceEntry[] entries,int index)throws IOException{ do{ PDFCrossReferenceSubSection subsection=new PDFCrossReferenceSubSection(); subsections.add(subsection); index=subsection.read(s,entries,index); s.scan(); }while(s.symbol==T_INTEGER); // if we find an integer instead of xref | trailer return index; } // read another cross-reference subsection public void write(PDFFile out)throws IOException{ offset = out.getOffset(); out.writeln("xref"); Enumeration e = subsections.elements(); while(e.hasMoreElements()){ PDFCrossReferenceSubSection subsection=(PDFCrossReferenceSubSection)e.nextElement(); subsection.write(out); } } } static public class PDFCrossReferenceSubSection{ // continuous range of object numbers // <cross-reference subsection> ::= // <object number of first entry> <number of entries> // <cross-reference entry>+ private int first = -1; private Vector entries = new Vector(); public void add(PDFCrossReferenceEntry obj){ entries.add(obj); } public int size(){ return entries.size(); } public int read(PDFScanner s,PDFCrossReferenceEntry[] entries,int index)throws IOException{ s.scan(); if(s.symbol!=T_INTEGER){throw new IOException(getClass().getName()+".read:\n\tSubsection: Missing object number of first entry.");} first = s.intval; // System.err.println("first "+first); s.scan(); if(s.symbol!=T_INTEGER){throw new IOException(getClass().getName()+".read:\n\tSubsection: Missing number of entries.");} int len = s.intval; // System.err.println("len "+len); for(int i=0;i<len;i++){ PDFCrossReferenceEntry entry=new PDFCrossReferenceEntry(index); entry.read(s); entries[index++]=entry; // System.err.println("entry "+entry.toString()); } return index; } public void write(PDFFile out)throws IOException{ Enumeration e = entries.elements(); if(e.hasMoreElements()){ PDFCrossReferenceEntry entry = (PDFCrossReferenceEntry)e.nextElement(); out.write(entry.getObjectNumber()); out.write(' '); out.write(entries.size()); out.writeln(); entry.write(out); while(e.hasMoreElements()){ entry=(PDFCrossReferenceEntry)e.nextElement(); entry.write(out); } } } } }