Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: 5.0.2
-
Fix Version/s: 5.1
-
Component/s: Core/Parsing
-
Labels:None
-
Environment:win xp prof
Description
-
- Activator.java
- 10 kB
- Stefan Franz
-
- AnnotationTester.java
- 3 kB
- Stefan Franz
-
- FileViewer.java
- 40 kB
- Stefan Franz
-
- mist.pdf
- 49 kB
- Stefan Franz
-
- mist.pdf.txt
- 1 kB
- Stefan Franz
-
- MySwingController.java
- 9 kB
- Stefan Franz
-
- MySwingController.java
- 5 kB
- Stefan Franz
-
- MySwingViewBuilder.java
- 1 kB
- Stefan Franz
-
- reader_overview.pdf
- 953 kB
- Stefan Franz
-
- reader_overview.pdf.txt
- 162 kB
- Stefan Franz
-
Hide
- viewer_plugin.zip
- 15 kB
- Stefan Franz
-
- diva_gui_viewer/sources/.../FileViewer.java 37 kB
- diva_gui_viewer/sources/.../Activator.java 10 kB
- diva_gui_viewer/.../MySwingController.java 8 kB
- diva_gui_viewer/.../MySwingViewBuilder.java 1 kB
- diva_gui_viewer/.../IcePdfAnnotation.java 0.9 kB
- diva_gui_viewer/.../IMarkupSaveHandler.java 0.1 kB
-
- screenshot-1.jpg
- 391 kB
-
- screenshot-2.jpg
- 338 kB
-
- screenshot-3.jpg
- 610 kB
Issue Links
- depends on
-
PDF-619 Text Markup annotations tool can result in duplicate annotations being created
- Closed
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
annotations reloaded from file (reader_overview.pdf.txt). annotations from page 3 (right) are completely missing. some annotations from page 2 (left) are inivisble or incorrect formatted.
original pdf file
saved annotations file
stack trace:
16.07.2013 09:16:37 org.icepdf.core.pobjects.Catalog <clinit>
INFO: ICEsoft ICEpdf Core 5.0.1
16.07.2013 09:16:37 org.icepdf.core.pobjects.fonts.nfont.Font <clinit>
INFO: ICEsoft ICEpdf Pro 5.0.2 P01
16.07.2013 09:16:42 org.icepdf.core.util.Parser getObject
WARNUNG: IO reading error.
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at test.MySwingController.loadMarkupFile(MySwingController.java:85)
at test.MySwingController.openURL(MySwingController.java:178)
at org.icepdf.ri.common.SwingController$8.run(SwingController.java:3672)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Overrides saveFile() method for saving the annotations to an external file and openURL() method to reload the annotations.
The SerializerText.java import code was meant to execute before a page component was initialized. Changes to the example need to be made to enable annotations to be loaded after a page component has been created.
It would be preferable to load the annotations to the document object directly, before the Viewer RI builds out the components. Does this match your expected usage case?
Related sub issue.
Could you provide more detail on the preferred work flow with regards to:
1) opening the annotation without annotations
2) injection of annotation information form external data source.
3) display of merged document with annotation data.
There are several ways of implementing this with the ICEpdf API and it is important the calls are made in the correct order to display the merged document correctly.
We integrated the ICEpdf in a existing eclipse rcp plugin and normally the user opens a document freh from our content management system without any annotations. Now he can add same markups and after that the annoations should be extracted and saved as a separate file in our cms. When he or another user opens that document again, both document and annation should be merged together and displayed in the viewer. I will provide you my implementation of the ICEpdf viewer ri.
1. Activator java starts the viewer plugin
2. FileViewer is the implementation of the surrounding JFrame
3. MySwingController overrides the original ICEpdf SwingController
4. MySwingViewBuilder ...same
Implementation of our eclipse rcp viewer plugin.
A bug was found with the existing annotation import code. The bug prevented an annotations content stream from being correctly parsed and painted. The resulting state did not provided enough information for the viewer to properly construct the annotations appearance stream.
The changes needed to correct this issue require changes to the core but with these changes the process of importing annotations has been simplified.
Assuming the call:
_ICEpdfController.openDocument("../reader_overview.pdf");
_ICEpdfController.loadExternalObjects();
Where loadExternalObjects() is defined as:
public void loadExternalObjects() {
try {
SeekableInput rafis =
RandomAccessFileInputStream.build(
new File(this.getDocument()
.getDocumentOrigin()
+ ".txt"));
Document document = this.getDocument();
Library library = document.getCatalog().getLibrary();
StateManager stateManager = library.getStateManager();
Parser parser = new Parser(rafis);
ArrayList<PObject> libraryObjects = new ArrayList<PObject>();
PObject object;
for (Object streamObject = parser.getObject(library); streamObject != null; streamObject = parser
.getObject(library))
// re-initialized page's and the annotations
document.getPageTree().resetInitializedState();
for (PObject pObject : libraryObjects) {
Object tmp = pObject.getObject();
if (tmp instanceof Page)
if (tmp instanceof Dictionary)
{ ((Dictionary) tmp).init(); }}
rafis.close();
} catch (FileNotFoundException e)
this.updateDocumentView();
}
Hi Patrick,
the following method dosn't exist:
document.getPageTree().resetInitializedState();
I'll be getting you a developer drop after the call which contains the new methods and fixes to the core. I've been testing locally and things look good but would like for you feedback before we do a full patch release.
Changes have been checked into the 5.0.1 branch and trunk.
Dear Patrick,
I downloaded the developer drop and tested a little bit. Reloading of the annotations seems better now. Unfortunatly I'am not able to change the once made annotations. If I reload them in the viewer I have to made a new annotation first. After that I'am able to change or delete the old ones. After saving these changed annotations I tried to reload them a second time but this failed with the following stacktrace:
22.07.2013 10:40:51 org.icepdf.core.pobjects.Catalog <clinit>
INFO: ICEsoft ICEpdf Core 5.0.1
22.07.2013 10:40:51 org.icepdf.core.pobjects.fonts.nfont.Font <clinit>
INFO: ICEsoft ICEpdf Pro 5.0.1
22.07.2013 10:41:02 org.icepdf.core.util.Parser getObject
WARNUNG: IO reading error.
22.07.2013 10:41:02 org.icepdf.core.util.content.NContentParser parse
WARNUNG: Error parsing content stream.
java.util.EmptyStackException
at java.util.Stack.peek(Unknown Source)
at java.util.Stack.pop(Unknown Source)
at org.icepdf.core.util.content.AbstractContentParser.consume_d(AbstractContentParser.java:642)
at org.icepdf.core.util.content.NContentParser.parse(Unknown Source)
at org.icepdf.core.pobjects.Form.init(Form.java:168)
at org.icepdf.core.pobjects.annotations.Annotation.init(Annotation.java:643)
at org.icepdf.core.pobjects.annotations.MarkupAnnotation.init(MarkupAnnotation.java:172)
at org.icepdf.core.pobjects.annotations.TextMarkupAnnotation.init(TextMarkupAnnotation.java:150)
at test.MySwingController.loadExternalObjects(MySwingController.java:223)
at test.MySwingController.openURL(MySwingController.java:187)
at org.icepdf.ri.common.SwingController$8.run(SwingController.java:3672)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
22.07.2013 10:41:02 org.icepdf.core.util.content.NContentParser parse
WARNUNG: Error parsing content stream.
java.util.EmptyStackException
at java.util.Stack.peek(Unknown Source)
at java.util.Stack.pop(Unknown Source)
at org.icepdf.core.util.content.AbstractContentParser.consume_K(AbstractContentParser.java:203)
at org.icepdf.core.util.content.NContentParser.parse(Unknown Source)
at org.icepdf.core.pobjects.Form.init(Form.java:168)
at org.icepdf.core.pobjects.annotations.Annotation.init(Annotation.java:643)
at org.icepdf.core.pobjects.annotations.MarkupAnnotation.init(MarkupAnnotation.java:172)
at org.icepdf.core.pobjects.annotations.TextMarkupAnnotation.init(TextMarkupAnnotation.java:150)
at test.MySwingController.loadExternalObjects(MySwingController.java:223)
at test.MySwingController.openURL(MySwingController.java:187)
at org.icepdf.ri.common.SwingController$8.run(SwingController.java:3672)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
This is my SwingController Implementation:
package test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import org.icepdf.core.io.RandomAccessFileInputStream;
import org.icepdf.core.io.SeekableInput;
import org.icepdf.core.pobjects.Dictionary;
import org.icepdf.core.pobjects.Document;
import org.icepdf.core.pobjects.PObject;
import org.icepdf.core.pobjects.Page;
import org.icepdf.core.pobjects.StateManager;
import org.icepdf.core.util.IncrementalUpdater;
import org.icepdf.core.util.Library;
import org.icepdf.core.util.Parser;
import org.icepdf.ri.common.SwingController;
public class MySwingController extends SwingController {
public MySwingController()
{ super(); }public void saveMarkupFile() throws Exception {
byte[][] updates = IncrementalUpdater.getUpdatedDocumentObjects(this
.getDocument());
String sFile = this.getDocument().getDocumentOrigin() + ".txt";
System.out.println("File: " + sFile);
FileOutputStream fileOutputStream = new FileOutputStream(sFile);
for (byte[] update : updates)
{ fileOutputStream.write(update); } fileOutputStream.close();
}
@Override
public void saveFile() {
if (!this.getDocument().getStateManager().isChanged()
&& !Document.foundIncrementalUpdater)
try
{ saveMarkupFile(); }catch (Exception e)
{ // TODO Auto-generated catch block e.printStackTrace(); }}
@Override
public void openURL() {
try { this.loadExternalObjects(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
public void loadExternalObjects() {
try {
SeekableInput rafis = RandomAccessFileInputStream.build(new File(
this.getDocument().getDocumentOrigin() + ".txt"));
Document document = this.getDocument();
Library library = document.getCatalog().getLibrary();
StateManager stateManager = library.getStateManager();
Parser parser = new Parser(rafis);
ArrayList<PObject> libraryObjects = new ArrayList<PObject>();
PObject object;
for (Object streamObject = parser.getObject(library); streamObject != null; streamObject = parser
.getObject(library))
// re-initialized page's and the annotations
document.getPageTree().resetInitializedState();
for (PObject pObject : libraryObjects) {
Object tmp = pObject.getObject();
if (tmp instanceof Page)
if (tmp instanceof Dictionary)
{ ((Dictionary) tmp).init(); } }
rafis.close();
} catch (FileNotFoundException e)
catch (Exception e)
{ e.printStackTrace(); } this.updateDocumentView();
}
}
Thanks for the feedback, I've updated my test to test for multiple saves during the same session. Two problem were discovered.
The first is that we were not correctly incremented the next available object numbers when doing the data import which was messing up the expected object hierarchy. This was the result of not have an updated xref table which would be the normal when saving the whole PDF document.
The second issue was related to re-saving a stream that as part of the import but not altered. The unaltered content streams were then recompressed and unreadable the next time around.
A new developer build has been prepped for testing.
some annotations still missing, here: blue circle annotation where you can see the "invisible" frame (small dotted line) around the annotation but not the annotation itself
Okay, thank you for the new test build. Some errors still occured:
- When I load annotations from stream now they won't be rendered immediately. Sometimes it took some seconds until they are visible.
- Existing rectangles and circles are not rendered sometimes (screenshot)
- There are some errors in log: 23.07.2013 14:37:07 org.icepdf.core.util.Parser getObject WARNUNG: IO reading error.
Stefan, thanks for the feedback, could you post you test import file?
I uploaded mist.pdf + annotation. The sample from the screenshot is from our content management system and could not saved localy.
Marking as resolved.
annotations created on pages 2 and 3 of the sample document. different types of annotations created. these annotations are saved in reader_overview.pdf.txt