diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/MarkupGlueAnnotation.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/MarkupGlueAnnotation.java index 84684488c..6ee6e5d79 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/MarkupGlueAnnotation.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/MarkupGlueAnnotation.java @@ -27,6 +27,8 @@ public MarkupGlueAnnotation(Library l, MarkupAnnotation markupAnnotation, PopupA } protected void renderAppearanceStream(Graphics2D g2d) { + if (this.popupAnnotation == null || this.markupAnnotation == null) return; + GraphicsConfiguration graphicsConfiguration = g2d.getDeviceConfiguration(); boolean isPrintingAllowed = this.markupAnnotation.getFlagPrint(); if (graphicsConfiguration.getDevice().getType() == GraphicsDevice.TYPE_PRINTER && @@ -38,7 +40,8 @@ protected void renderAppearanceStream(Graphics2D g2d) { } public Rectangle2D.Float getUserSpaceRectangle() { - if (userSpaceRectangle == null) { + // make sure we always update this to get the correct clip during painting + if (this.markupAnnotation != null && this.popupAnnotation != null) { Rectangle rect = this.markupAnnotation.getUserSpaceRectangle().getBounds().union( this.popupAnnotation.getUserSpaceRectangle().getBounds()); userSpaceRectangle = new Rectangle2D.Float(rect.x, rect.y, rect.width, rect.height); @@ -54,4 +57,8 @@ public boolean allowPrintNormalMode() { public void resetAppearanceStream(double dx, double dy, AffineTransform pageSpace, boolean isNew) { } + + public MarkupAnnotation getMarkupAnnotation() { + return markupAnnotation; + } } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/Page.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/Page.java index ba7142d3c..d8a136a7c 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/Page.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/Page.java @@ -355,11 +355,7 @@ else if (annotObj instanceof HashMap) { // HashMap lacks "Type"->"Annot" entry } // create synthetic annotation to paint the glue between a markup annotation and the popup // this is only used for print purposes. A similar pattern is also used in the Viewer RI - if (a instanceof MarkupAnnotation) { - MarkupAnnotation markupAnnotation = (MarkupAnnotation) a; - PopupAnnotation popupAnnotation = markupAnnotation.getPopupAnnotation(); - annotations.add(new MarkupGlueAnnotation(library, markupAnnotation, popupAnnotation)); - } + createPrintableMarkupAnnotationGlue(a); } } catch (IllegalStateException e) { logger.warning("Malformed annotation could not be initialized. " + @@ -814,6 +810,24 @@ public Shape getPageShape(int boundary, float userRotation, float userZoom) { return path.createTransformedShape(at); } + private void createPrintableMarkupAnnotationGlue(Annotation annotation) { + // create synthetic annotation to paint the glue between a markup annotation and the popup + // this is only used for print purposes. A similar pattern is also used in the Viewer RI + if (annotation instanceof PopupAnnotation) { + PopupAnnotation popupAnnotation = (PopupAnnotation) annotation; + MarkupAnnotation markupAnnotation = popupAnnotation.getParent(); + // insert glue before popup is painted, so we don't over paint + Annotation annot; + for (int i = 0; i < annotations.size(); i++) { + annot = annotations.get(i); + if (annot instanceof PopupAnnotation && annot.equals(popupAnnotation)) { + annotations.add(i, new MarkupGlueAnnotation(library, markupAnnotation, popupAnnotation)); + break; + } + } + } + } + /** * Adds an annotation that was previously added to the document. It is * assumed that the annotation has a valid object reference. This @@ -821,8 +835,8 @@ public Shape getPageShape(int boundary, float userRotation, float userZoom) { * the method @link{#createAnnotation} for creating new annotations. * * @param newAnnotation annotation object to add - * @param isNew annotation is new and should be added to stateManager, otherwise change will be part of the document - * but not yet added to the stateManager as the change was likely a missing content stream or popup. + * @param isNew annotation is new and should be added to stateManager, otherwise change will be part of the document + * but not yet added to the stateManager as the change was likely a missing content stream or popup. * @return reference to annotation that was added. */ @SuppressWarnings("unchecked") @@ -888,6 +902,9 @@ public Annotation addAnnotation(Annotation newAnnotation, boolean isNew) { // add the annotations to the parsed annotations list this.annotations.add(newAnnotation); + // add visual glue for markup annotation + createPrintableMarkupAnnotationGlue(newAnnotation); + // add the new annotations to the library library.addObject(newAnnotation, newAnnotation.getPObjectReference()); @@ -976,6 +993,30 @@ else if (annot.isNew()) { if (annotations != null) { annotations.remove(annot); } + // todo clean up orphaned popup annotations + // remove any corresponding popup annotation. + if (annot instanceof MarkupAnnotation) { + MarkupAnnotation markupAnnotation = (MarkupAnnotation) annot; + for (Annotation annotation : annotations) { + if (annotation instanceof PopupAnnotation && + annotation.equals(markupAnnotation.getPopupAnnotation())) { + annotations.remove(annotation); + break; + } + } + } + // remove any markupGlue so that it doesn't get painted. Glue is never added to the document, it created + // dynamically for print purposes. + if (annot instanceof MarkupAnnotation) { + MarkupAnnotation markupAnnotation = (MarkupAnnotation) annot; + for (Annotation annotation : annotations) { + if (annotation instanceof MarkupGlueAnnotation && + ((MarkupGlueAnnotation) annotation).getMarkupAnnotation().equals(markupAnnotation)) { + annotations.remove(annotation); + break; + } + } + } // finally remove it from the library to free up the memory library.removeObject(annot.getPObjectReference()); } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/Annotation.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/Annotation.java index 4912d8dd8..c7caaf762 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/Annotation.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/Annotation.java @@ -1316,7 +1316,10 @@ public void render(Graphics2D origG, int renderHintType, g.setRenderingHints(grh.getRenderingHints(renderHintType)); g.setTransform(at); Shape preAppearanceStreamClip = g.getClip(); - g.clip(deriveDrawingRectangle()); + Rectangle2D.Float derivedClip = deriveDrawingRectangle(); + if (derivedClip != null) { + g.clip(deriveDrawingRectangle()); + } renderAppearanceStream(g); diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/PopupAnnotation.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/PopupAnnotation.java index b39a9b9d8..98c985bb4 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/PopupAnnotation.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/annotations/PopupAnnotation.java @@ -132,8 +132,7 @@ protected void renderAppearanceStream(Graphics2D g2d) { if (graphicsConfiguration.getDevice().getType() == GraphicsDevice.TYPE_PRINTER && isOpen() && isPrintingAllowed) { - String contents = getParent() != null ? getParent().getContents() : ""; - if (contents != null && resetPopupPaintables) { + if (resetPopupPaintables) { buildPopupPaintables(); } paintPopupPaintables(g2d);