All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.itextpdf.kernel.pdf.annot.PdfAnnotation Maven / Gradle / Ivy

There is a newer version: 9.0.0
Show newest version
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2024 Apryse Group NV
    Authors: Apryse Software.

    This program is offered under a commercial and under the AGPL license.
    For commercial licensing, contact us at https://itextpdf.com/sales.  For AGPL licensing, see below.

    AGPL licensing:
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see .
 */
package com.itextpdf.kernel.pdf.annot;

import com.itextpdf.io.logs.IoLogMessageConstant;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.colors.Color;
import com.itextpdf.kernel.colors.DeviceCmyk;
import com.itextpdf.kernel.colors.DeviceGray;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfAnnotationBorder;
import com.itextpdf.kernel.pdf.PdfArray;
import com.itextpdf.kernel.pdf.PdfDictionary;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfIndirectReference;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfNumber;
import com.itextpdf.kernel.pdf.PdfObject;
import com.itextpdf.kernel.pdf.PdfObjectWrapper;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.filespec.PdfFileSpec;
import com.itextpdf.kernel.pdf.layer.IPdfOCG;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is a super class for the annotation dictionary wrappers. Derived classes represent
 * different standard types of annotations. See ISO-320001 12.5.6, "Annotation Types."
 */
public abstract class PdfAnnotation extends PdfObjectWrapper {


    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int INVISIBLE = 1;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int HIDDEN = 2;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int PRINT = 4;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int NO_ZOOM = 8;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int NO_ROTATE = 16;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int NO_VIEW = 32;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int READ_ONLY = 64;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int LOCKED = 128;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int TOGGLE_NO_VIEW = 256;

    /**
     * Annotation flag.
     * See also {@link PdfAnnotation#setFlag(int)} and ISO-320001, table 165.
     */
    public static final int LOCKED_CONTENTS = 512;


    /**
     * Widget annotation highlighting mode. See ISO-320001, Table 188 (H key).
     * Also see {@link PdfWidgetAnnotation#setHighlightMode(PdfName)}.
     */
    public static final PdfName HIGHLIGHT_NONE = PdfName.N;

    /**
     * Widget annotation highlighting mode. See ISO-320001, Table 188 (H key).
     * Also see {@link PdfWidgetAnnotation#setHighlightMode(PdfName)}.
     */
    public static final PdfName HIGHLIGHT_INVERT = PdfName.I;

    /**
     * Widget annotation highlighting mode. See ISO-320001, Table 188 (H key).
     * Also see {@link PdfWidgetAnnotation#setHighlightMode(PdfName)}.
     */
    public static final PdfName HIGHLIGHT_OUTLINE = PdfName.O;

    /**
     * Widget annotation highlighting mode. See ISO-320001, Table 188 (H key).
     * Also see {@link PdfWidgetAnnotation#setHighlightMode(PdfName)}.
     */
    public static final PdfName HIGHLIGHT_PUSH = PdfName.P;

    /**
     * Widget annotation highlighting mode. See ISO-320001, Table 188 (H key).
     * Also see {@link PdfWidgetAnnotation#setHighlightMode(PdfName)}.
     */
    public static final PdfName HIGHLIGHT_TOGGLE = PdfName.T;


    /**
     * Annotation border style. See ISO-320001, Table 166 (S key).
     */
    public static final PdfName STYLE_SOLID = PdfName.S;

    /**
     * Annotation border style. See ISO-320001, Table 166 (S key).
     */
    public static final PdfName STYLE_DASHED = PdfName.D;

    /**
     * Annotation border style. See ISO-320001, Table 166 (S key).
     */
    public static final PdfName STYLE_BEVELED = PdfName.B;

    /**
     * Annotation border style. See ISO-320001, Table 166 (S key).
     */
    public static final PdfName STYLE_INSET = PdfName.I;

    /**
     * Annotation border style. See ISO-320001, Table 166 (S key).
     */
    public static final PdfName STYLE_UNDERLINE = PdfName.U;


    /**
     * Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular.
     * Also see {@link PdfTextAnnotation#setState(PdfString)}.
     */
    public static final PdfString Marked = new PdfString("Marked");

    /**
     * Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular.
     * Also see {@link PdfTextAnnotation#setState(PdfString)}.
     */
    public static final PdfString Unmarked = new PdfString("Unmarked");

    /**
     * Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular.
     * Also see {@link PdfTextAnnotation#setState(PdfString)}.
     */
    public static final PdfString Accepted = new PdfString("Accepted");

    /**
     * Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular.
     * Also see {@link PdfTextAnnotation#setState(PdfString)}.
     */
    public static final PdfString Rejected = new PdfString("Rejected");

    /**
     * Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular.
     * Also see {@link PdfTextAnnotation#setState(PdfString)}.
     */
    public static final PdfString Canceled = new PdfString("Cancelled");

    /**
     * Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular.
     * Also see {@link PdfTextAnnotation#setState(PdfString)}.
     */
    public static final PdfString Completed = new PdfString("Completed");

    /**
     * Annotation state. See ISO-320001 12.5.6.3 "Annotation States" and Table 171 in particular.
     * Also see {@link PdfTextAnnotation#setState(PdfString)}.
     */
    public static final PdfString None = new PdfString("None");


    /**
     * Annotation state model. See ISO-320001, Table 172 (StateModel key).
     * Also see {@link PdfTextAnnotation#setStateModel(PdfString)}.
     */
    public static final PdfString MarkedModel = new PdfString("Marked");

    /**
     * Annotation state model. See ISO-320001, Table 172 (StateModel key).
     * Also see {@link PdfTextAnnotation#setStateModel(PdfString)}.
     */
    public static final PdfString ReviewModel = new PdfString("Review");

    protected PdfPage page;

    /**
     * Factory method that creates the type specific {@link PdfAnnotation} from the given {@link PdfObject}
     * that represents annotation object. This method is useful for property reading in reading mode or
     * modifying in stamping mode. See derived classes of this class to see possible specific annotation types
     * created.
     *
     * @param pdfObject a {@link PdfObject} that represents annotation in the document.
     * @return created {@link PdfAnnotation}.
     */
    public static PdfAnnotation makeAnnotation(PdfObject pdfObject) {
        PdfAnnotation annotation = null;
        if (pdfObject.isIndirectReference())
            pdfObject = ((PdfIndirectReference) pdfObject).getRefersTo();
        if (pdfObject.isDictionary()) {
            PdfDictionary dictionary = (PdfDictionary) pdfObject;
            PdfName subtype = dictionary.getAsName(PdfName.Subtype);
            if (PdfName.Link.equals(subtype)) {
                annotation = new PdfLinkAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Popup.equals(subtype)) {
                annotation = new PdfPopupAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Widget.equals(subtype)) {
                annotation = new PdfWidgetAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Screen.equals(subtype)) {
                annotation = new PdfScreenAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName._3D.equals(subtype)) {
                annotation = new Pdf3DAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Highlight.equals(subtype) || PdfName.Underline.equals(subtype) || PdfName.Squiggly.equals(subtype) || PdfName.StrikeOut.equals(subtype)) {
                annotation = new PdfTextMarkupAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Caret.equals(subtype)) {
                annotation = new PdfCaretAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Text.equals(subtype)) {
                annotation = new PdfTextAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Sound.equals(subtype)) {
                annotation = new PdfSoundAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Stamp.equals(subtype)) {
                annotation = new PdfStampAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.FileAttachment.equals(subtype)) {
                annotation = new PdfFileAttachmentAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Ink.equals(subtype)) {
                annotation = new PdfInkAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.PrinterMark.equals(subtype)) {
                annotation = new PdfPrinterMarkAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.TrapNet.equals(subtype)) {
                annotation = new PdfTrapNetworkAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.FreeText.equals(subtype)) {
                annotation = new PdfFreeTextAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Square.equals(subtype)) {
                annotation = new PdfSquareAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Circle.equals(subtype)) {
                annotation = new PdfCircleAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Line.equals(subtype)) {
                annotation = new PdfLineAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Polygon.equals(subtype)) {
                annotation = new PdfPolygonAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.PolyLine.equals(subtype)) {
                annotation = new PdfPolylineAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Redact.equals(subtype)) {
                annotation = new PdfRedactAnnotation((PdfDictionary) pdfObject);
            } else if (PdfName.Watermark.equals(subtype)) {
                annotation = new PdfWatermarkAnnotation((PdfDictionary) pdfObject);
            } else {
                annotation = new PdfUnknownAnnotation((PdfDictionary) pdfObject);
            }
        }
        return annotation;
    }

    protected PdfAnnotation(Rectangle rect) {
        this(new PdfDictionary());
        put(PdfName.Rect, new PdfArray(rect));
        put(PdfName.Subtype, getSubtype());
    }

    protected PdfAnnotation(PdfDictionary pdfObject) {
        super(pdfObject);
        markObjectAsIndirect(getPdfObject());
    }

    /**
     * Gets a {@link PdfName} which value is a subtype of this annotation.
     * See ISO-320001 12.5.6, "Annotation Types" for the reference to the possible types.
     *
     * @return subtype of this annotation.
     */
    public abstract PdfName getSubtype();

    /**
     * Sets the layer this annotation belongs to.
     *
     * @param layer the layer this annotation belongs to
     */
    public void setLayer(IPdfOCG layer) {
        getPdfObject().put(PdfName.OC, layer.getIndirectReference());
    }

    /**
     * Gets the text that shall be displayed for the annotation or, if this type of annotation does not display text,
     * an alternate description of the annotation’s contents in human-readable form.
     *
     * @return annotation text content.
     */
    public PdfString getContents() {
        return getPdfObject().getAsString(PdfName.Contents);
    }

    /**
     * Sets the text that shall be displayed for the annotation or, if this type of annotation does not display text,
     * an alternate description of the annotation’s contents in human-readable form.
     *
     * @param contents a {@link PdfString} containing text content to be set to the annotation.
     * @return this {@link PdfAnnotation} instance.
     */
    public PdfAnnotation setContents(PdfString contents) {
        return put(PdfName.Contents, contents);
    }

    /**
     * Sets the text that shall be displayed for the annotation or, if this type of annotation does not display text,
     * an alternate description of the annotation’s contents in human-readable form.
     *
     * @param contents a java {@link String} containing text content to be set to the annotation.
     * @return this {@link PdfAnnotation} instance.
     */
    public PdfAnnotation setContents(String contents) {
        return setContents(new PdfString(contents, PdfEncodings.UNICODE_BIG));
    }

    /**
     * Gets a {@link PdfDictionary} that represents a page of the document on which annotation is placed,
     * i.e. which has this annotation in it's /Annots array.
     *
     * @return {@link PdfDictionary} that is a page pdf object or null if annotation is not added to the page yet.
     */
    public PdfDictionary getPageObject() {
        return getPdfObject().getAsDictionary(PdfName.P);
    }

    /**
     * Gets a {@link PdfPage} on which annotation is placed.
     *
     * @return {@link PdfPage} on which annotation is placed or null if annotation is not placed yet.
     */
    public PdfPage getPage() {
        PdfIndirectReference annotationIndirectReference;
        if (page == null && (annotationIndirectReference = getPdfObject().getIndirectReference()) != null) {
            PdfDocument doc = annotationIndirectReference.getDocument();

            PdfDictionary pageDictionary = getPageObject();
            if (pageDictionary != null) {
                page = doc.getPage(pageDictionary);
            } else {
                for (int i = 1; i <= doc.getNumberOfPages(); i++) {
                    PdfPage docPage = doc.getPage(i);
                    if (!docPage.isFlushed()) {
                        for (PdfAnnotation annot : docPage.getAnnotations()) {
                            if (annotationIndirectReference.equals(annot.getPdfObject().getIndirectReference())) {
                                page = docPage;
                                break;
                            }
                        }
                    }
                }
            }


        }
        return page;
    }

    /**
     * Method that modifies annotation page property, which defines to which page annotation belongs.
     * Keep in mind that this doesn't actually add an annotation to the page,
     * it should be done via {@link PdfPage#addAnnotation(PdfAnnotation)}.
     * Also you don't need to set this property manually, this is done automatically on addition to the page.
     *
     * @param page the {@link PdfPage} to which annotation will be added.
     * @return this {@link PdfAnnotation} instance.
     */
    public PdfAnnotation setPage(PdfPage page) {
        this.page = page;
        // Explicitly using object indirect reference here in order to correctly process released objects.
        return put(PdfName.P, page.getPdfObject().getIndirectReference());
    }

    /**
     * Gets the annotation name, a text string uniquely identifying it among all the
     * annotations on its page.
     *
     * @return a {@link PdfString} with annotation name as it's value or null if name
     * is not specified.
     */
    public PdfString getName() {
        return getPdfObject().getAsString(PdfName.NM);
    }

    /**
     * Sets the annotation name, a text string uniquely identifying it among all the
     * annotations on its page.
     *
     * @param name a {@link PdfString} to be set as annotation name.
     * @return this {@link PdfAnnotation} instance.
     */
    public PdfAnnotation setName(PdfString name) {
        return put(PdfName.NM, name);
    }

    /**
     * The date and time when the annotation was most recently modified.
     * This is an optional property of the annotation.
     *
     * @return a {@link PdfString} with the modification date as it's value or null if date is not specified.
     */
    public PdfString getDate() {
        return getPdfObject().getAsString(PdfName.M);
    }

    /**
     * The date and time when the annotation was most recently modified.
     *
     * @param date a {@link PdfString} with date. The format should be a date string as described
     *             in ISO-320001 7.9.4, "Dates".
     * @return this {@link PdfAnnotation} instance.
     */
    public PdfAnnotation setDate(PdfString date) {
        return put(PdfName.M, date);
    }

    /**
     * A set of flags specifying various characteristics of the annotation (see ISO-320001 12.5.3, "Annotation Flags").
     * For specific annotation flag constants see {@link PdfAnnotation#setFlag(int)}.
     * Default value: 0.
     *
     * @return an integer interpreted as one-bit flags specifying various characteristics of the annotation.
     */
    public int getFlags() {
        PdfNumber f = getPdfObject().getAsNumber(PdfName.F);
        if (f != null)
            return f.intValue();
        else
            return 0;
    }

    /**
     * Sets a set of flags specifying various characteristics of the annotation (see ISO-320001 12.5.3, "Annotation Flags").
     * On the contrary from {@link PdfAnnotation#setFlag(int)}, this method sets a complete set of enabled and disabled flags at once.
     * If not set specifically the default value is 0.
     *
     * @param flags an integer interpreted as set of one-bit flags specifying various characteristics of the annotation.
     * @return this {@link PdfAnnotation} instance.
     */
    public PdfAnnotation setFlags(int flags) {
        return put(PdfName.F, new PdfNumber(flags));
    }

    /**
     * Sets a flag that specifies a characteristic of the annotation to enabled state (see ISO-320001 12.5.3, "Annotation Flags").
     * On the contrary from {@link PdfAnnotation#setFlags(int)}, this method sets only specified flags to enabled state,
     * but doesn't disable other flags.
     * Possible flags:
     * 
    *
  • {@link PdfAnnotation#INVISIBLE} - If set, do not display the annotation if it does not belong to one of the * standard annotation types and no annotation handler is available. If clear, display such unknown annotation * using an appearance stream specified by its appearance dictionary, if any. * *
  • {@link PdfAnnotation#HIDDEN} - If set, do not display or print the annotation or allow it to interact with * the user, regardless of its annotation type or whether an annotation handler is available. * *
  • {@link PdfAnnotation#PRINT} - If set, print the annotation when the page is printed. If clear, never print * the annotation, regardless of whether it is displayed on the screen. * *
  • {@link PdfAnnotation#NO_ZOOM} - If set, do not scale the annotation’s appearance to match the magnification of * the page. The location of the annotation on the page (defined by the upper-left corner of its annotation * rectangle) shall remain fixed, regardless of the page magnification.} * *
  • {@link PdfAnnotation#NO_ROTATE} - If set, do not rotate the annotation’s appearance to match the rotation * of the page. The upper-left corner of the annotation rectangle shall remain in a fixed location on the page, * regardless of the page rotation. * *
  • {@link PdfAnnotation#NO_VIEW} - If set, do not display the annotation on the screen or allow it to interact * with the user. The annotation may be printed (depending on the setting of the Print flag) but should be considered * hidden for purposes of on-screen display and user interaction. * *
  • {@link PdfAnnotation#READ_ONLY} - If set, do not allow the annotation to interact with the user. The annotation * may be displayed or printed (depending on the settings of the NoView and Print flags) but should not respond to mouse * clicks or change its appearance in response to mouse motions. * *
  • {@link PdfAnnotation#LOCKED} - If set, do not allow the annotation to be deleted or its properties * (including position and size) to be modified by the user. However, this flag does not restrict changes to * the annotation’s contents, such as the value of a form field. * *
  • {@link PdfAnnotation#TOGGLE_NO_VIEW} - If set, invert the interpretation of the NoView flag for certain events. * *
  • {@link PdfAnnotation#LOCKED_CONTENTS} - If set, do not allow the contents of the annotation to be modified * by the user. This flag does not restrict deletion of the annotation or changes to other annotation properties, * such as position and size. * *
* * @param flag - an integer interpreted as set of one-bit flags which will be enabled for this annotation. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setFlag(int flag) { int flags = getFlags(); flags = flags | flag; return setFlags(flags); } /** * Resets a flag that specifies a characteristic of the annotation to disabled state (see ISO-320001 12.5.3, "Annotation Flags"). * * @param flag an integer interpreted as set of one-bit flags which will be reset to disabled state. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation resetFlag(int flag) { int flags = getFlags(); flags = flags & ~flag; return setFlags(flags); } /** * Checks if the certain flag that specifies a characteristic of the annotation * is in enabled state (see ISO-320001 12.5.3, "Annotation Flags"). * This method allows only one flag to be checked at once, use constants listed in {@link PdfAnnotation#setFlag(int)}. * * @param flag an integer interpreted as set of one-bit flags. Only one bit must be set in this integer, otherwise * exception is thrown. * @return true if the given flag is in enabled state. */ public boolean hasFlag(int flag) { if (flag == 0) { return false; } if ((flag & flag - 1) != 0) { throw new IllegalArgumentException("Only one flag must be checked at once."); } int flags = getFlags(); return (flags & flag) != 0; } /** * An appearance dictionary specifying how the annotation shall be presented visually on the page during its * interactions with the user (see ISO-320001 12.5.5, "Appearance Streams"). An appearance dictionary is a dictionary * containing one or several appearance streams or subdictionaries. * * @return an appearance {@link PdfDictionary} or null if it is not specified. */ public PdfDictionary getAppearanceDictionary() { return getPdfObject().getAsDictionary(PdfName.AP); } /** * Specific appearance object corresponding to the specific appearance type. This object might be either an appearance * stream or an appearance subdictionary. In the latter case, the subdictionary defines multiple appearance streams * corresponding to different appearance states of the annotation. See ISO-320001 12.5.5, "Appearance Streams". * * @param appearanceType a {@link PdfName} specifying appearance type. Possible types are {@link PdfName#N Normal}, * {@link PdfName#R Rollover} and {@link PdfName#D Down}. * @return null if their is no such appearance type or an appearance object which might be either * an appearance stream or an appearance subdictionary. */ public PdfDictionary getAppearanceObject(PdfName appearanceType) { PdfDictionary ap = getAppearanceDictionary(); if (ap != null) { PdfObject apObject = ap.get(appearanceType); if (apObject instanceof PdfDictionary) { return (PdfDictionary) apObject; } } return null; } /** * The normal appearance is used when the annotation is not interacting with the user. * This appearance is also used for printing the annotation. * See also {@link PdfAnnotation#getAppearanceObject(PdfName)}. * * @return an appearance object which might be either an appearance stream or an appearance subdictionary. */ public PdfDictionary getNormalAppearanceObject() { return getAppearanceObject(PdfName.N); } /** * The rollover appearance is used when the user moves the cursor into the annotation’s active area * without pressing the mouse button. If not specified normal appearance is used. * See also {@link PdfAnnotation#getAppearanceObject(PdfName)}. * * @return null if rollover appearance is not specified or an appearance object which might be either * an appearance stream or an appearance subdictionary. */ public PdfDictionary getRolloverAppearanceObject() { return getAppearanceObject(PdfName.R); } /** * The down appearance is used when the mouse button is pressed or held down within the annotation’s active area. * If not specified normal appearance is used. * See also {@link PdfAnnotation#getAppearanceObject(PdfName)}. * * @return null if down appearance is not specified or an appearance object which might be either * an appearance stream or an appearance subdictionary. */ public PdfDictionary getDownAppearanceObject() { return getAppearanceObject(PdfName.D); } /** * Sets a specific type of the appearance. See {@link PdfAnnotation#getAppearanceObject(PdfName)} and * {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearanceType a {@link PdfName} specifying appearance type. Possible types are {@link PdfName#N Normal}, * {@link PdfName#R Rollover} and {@link PdfName#D Down}. * @param appearance an appearance object which might be either an appearance stream or an appearance subdictionary. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setAppearance(PdfName appearanceType, PdfDictionary appearance) { PdfDictionary ap = getAppearanceDictionary(); if (ap == null) { ap = new PdfDictionary(); getPdfObject().put(PdfName.AP, ap); } ap.put(appearanceType, appearance); return this; } /** * Sets normal appearance. See {@link PdfAnnotation#getNormalAppearanceObject()} and * {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearance an appearance object which might be either an appearance stream or an appearance subdictionary. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setNormalAppearance(PdfDictionary appearance) { return setAppearance(PdfName.N, appearance); } /** * Sets rollover appearance. See {@link PdfAnnotation#getRolloverAppearanceObject()} and * {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearance an appearance object which might be either an appearance stream or an appearance subdictionary. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setRolloverAppearance(PdfDictionary appearance) { return setAppearance(PdfName.R, appearance); } /** * Sets down appearance. See {@link PdfAnnotation#getDownAppearanceObject()} and * {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearance an appearance object which might be either an appearance stream or an appearance subdictionary. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setDownAppearance(PdfDictionary appearance) { return setAppearance(PdfName.D, appearance); } /** * Sets a specific type of the appearance using {@link PdfAnnotationAppearance} wrapper. * This method is used to set only an appearance subdictionary. See {@link PdfAnnotation#getAppearanceObject(PdfName)} * and {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearanceType a {@link PdfName} specifying appearance type. Possible types are {@link PdfName#N Normal}, * {@link PdfName#R Rollover} and {@link PdfName#D Down}. * @param appearance an appearance subdictionary wrapped in {@link PdfAnnotationAppearance}. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setAppearance(PdfName appearanceType, PdfAnnotationAppearance appearance) { return setAppearance(appearanceType, appearance.getPdfObject()); } /** * Sets normal appearance using {@link PdfAnnotationAppearance} wrapper. This method is used to set only * appearance subdictionary. See {@link PdfAnnotation#getNormalAppearanceObject()} and * {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearance an appearance subdictionary wrapped in {@link PdfAnnotationAppearance}. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setNormalAppearance(PdfAnnotationAppearance appearance) { return setAppearance(PdfName.N, appearance); } /** * Sets rollover appearance using {@link PdfAnnotationAppearance} wrapper. This method is used to set only * appearance subdictionary. See {@link PdfAnnotation#getRolloverAppearanceObject()} and * {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearance an appearance subdictionary wrapped in {@link PdfAnnotationAppearance}. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setRolloverAppearance(PdfAnnotationAppearance appearance) { return setAppearance(PdfName.R, appearance); } /** * Sets down appearance using {@link PdfAnnotationAppearance} wrapper. This method is used to set only * appearance subdictionary. See {@link PdfAnnotation#getDownAppearanceObject()} and * {@link PdfAnnotation#getAppearanceDictionary()} for more info. * * @param appearance an appearance subdictionary wrapped in {@link PdfAnnotationAppearance}. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setDownAppearance(PdfAnnotationAppearance appearance) { return setAppearance(PdfName.D, appearance); } /** * The annotation’s appearance state, which selects the applicable appearance stream * from an appearance subdictionary if there is such. See {@link PdfAnnotation#getAppearanceObject(PdfName)} * for more info. * * @return a {@link PdfName} which defines selected appearance state. */ public PdfName getAppearanceState() { return getPdfObject().getAsName(PdfName.AS); } /** * Sets the annotation’s appearance state, which selects the applicable appearance stream * from an appearance subdictionary. See {@link PdfAnnotation#getAppearanceObject(PdfName)} * for more info. * * @param as a {@link PdfName} which defines appearance state to be selected. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setAppearanceState(PdfName as) { return put(PdfName.AS, as); } /** * An array specifying the characteristics of the annotation’s border. * The array consists of three numbers defining the horizontal corner radius, * vertical corner radius, and border width, all in default user space units. * If the corner radii are 0, the border has square (not rounded) corners; if * the border width is 0, no border is drawn. *

* The array may have a fourth element, an optional dash array (see ISO-320001 8.4.3.6, "Line Dash Pattern"). * * @return an {@link PdfArray} specifying the characteristics of the annotation’s border. */ public PdfArray getBorder() { return getPdfObject().getAsArray(PdfName.Border); } /** * Sets the characteristics of the annotation’s border. * * @param border an {@link PdfAnnotationBorder} specifying the characteristics of the annotation’s border. * See {@link PdfAnnotation#getBorder()} for more detailes. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setBorder(PdfAnnotationBorder border) { return put(PdfName.Border, border.getPdfObject()); } /** * Sets the characteristics of the annotation’s border. * * @param border an {@link PdfArray} specifying the characteristics of the annotation’s border. * See {@link PdfAnnotation#getBorder()} for more detailes. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setBorder(PdfArray border) { return put(PdfName.Border, border); } /** * An array of numbers in the range 0.0 to 1.0, representing a colour used for the following purposes: *

    *
  • The background of the annotation’s icon when closed *
  • The title bar of the annotation’s pop-up window *
  • The border of a link annotation *
* The number of array elements determines the colour space in which the colour shall be defined: *
    *
  • 0 - No colour; transparent *
  • 1 - DeviceGray *
  • 3 - DeviceRGB *
  • 4 - DeviceCMYK *
* * @return An array of numbers in the range 0.0 to 1.0, representing an annotation colour. */ public PdfArray getColorObject() { return getPdfObject().getAsArray(PdfName.C); } /** * Sets an annotation color. For more details on annotation color purposes and the format * of the passing {@link PdfArray} see {@link PdfAnnotation#getColorObject()}. * * @param color an array of numbers in the range 0.0 to 1.0, specifying color. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setColor(PdfArray color) { return put(PdfName.C, color); } /** * Sets an annotation color. For more details on annotation color purposes and the format * of the passing array see {@link PdfAnnotation#getColorObject()}. * * @param color an array of numbers in the range 0.0 to 1.0, specifying color. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setColor(float[] color) { return setColor(new PdfArray(color)); } /** * Sets an annotation color. For more details on annotation color purposes * see {@link PdfAnnotation#getColorObject()}. * * @param color {@link Color} object of the either {@link DeviceGray}, * {@link DeviceRgb} or {@link DeviceCmyk} type. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setColor(Color color) { return setColor(new PdfArray(color.getColorValue())); } /** * The integer key of the annotation’s entry in the structural parent tree * (see ISO-320001 14.7.4.4, "Finding Structure Elements from Content Items"). * * @return integer key in structural parent tree or -1 if annotation is not tagged. */ public int getStructParentIndex() { PdfNumber n = getPdfObject().getAsNumber(PdfName.StructParent); if (n == null) return -1; else return n.intValue(); } /** * Sets he integer key of the annotation’s entry in the structural parent tree * (see ISO-320001 14.7.4.4, "Finding Structure Elements from Content Items"). * Note: Normally, there is no need to take care of this manually, struct parent index is set automatically * if annotation is added to the tagged document's page. * * @param structParentIndex integer which is to be the key of the annotation's entry * in structural parent tree. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setStructParentIndex(int structParentIndex) { return put(PdfName.StructParent, new PdfNumber(structParentIndex)); } /** * Sets annotation title. This property affects not all annotation types. * * @param title a {@link PdfString} which value is to be annotation title. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setTitle(PdfString title) { return put(PdfName.T, title); } /** * Annotation title. For example for markup annotations, the title is the text label that shall be displayed in the * title bar of the annotation’s pop-up window when open and active. For movie annotation Movie actions * (ISO-320001 12.6.4.9, "Movie Actions") may use this title to reference the movie annotation. * * @return {@link PdfString} which value is an annotation title or null if it isn't specified. */ public PdfString getTitle() { return getPdfObject().getAsString(PdfName.T); } /** * The annotation rectangle, defining the location of the annotation on the page in default user space units. * * @param array a {@link PdfArray} which specifies a rectangle by two diagonally opposite corners. * Typically, the array is of form [llx lly urx ury]. * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation setRectangle(PdfArray array) { return put(PdfName.Rect, array); } /** * The annotation rectangle, defining the location of the annotation on the page in default user space units. * * @return a {@link PdfArray} which specifies a rectangle by two diagonally opposite corners. * Typically, the array is of form [llx lly urx ury]. */ public PdfArray getRectangle() { return getPdfObject().getAsArray(PdfName.Rect); } /** * PDF 2.0. A language identifier overriding the document’s language identifier to * specify the natural language for all text in the annotation except where overridden by * other explicit language specifications * * @return the lang entry */ public String getLang() { PdfString lang = getPdfObject().getAsString(PdfName.Lang); return lang != null ? lang.toUnicodeString() : null; } /** * PDF 2.0. A language identifier overriding the document’s language identifier to * specify the natural language for all text in the annotation except where overridden by * other explicit language specifications * * @param lang language identifier * @return this {@link PdfAnnotation} instance */ public PdfAnnotation setLang(String lang) { return put(PdfName.Lang, new PdfString(lang, PdfEncodings.UNICODE_BIG)); } /** * PDF 2.0. The blend mode that shall be used when painting the annotation onto the page * * @return the blend mode */ public PdfName getBlendMode() { return getPdfObject().getAsName(PdfName.BM); } /** * PDF 2.0. The blend mode that shall be used when painting the annotation onto the page * * @param blendMode blend mode * @return this {@link PdfAnnotation} instance */ public PdfAnnotation setBlendMode(PdfName blendMode) { return put(PdfName.BM, blendMode); } /** * PDF 2.0. When regenerating the annotation's appearance stream, this is the * opacity value that shall be used for all nonstroking * operations on all visible elements of the annotation in its closed state (including its * background and border) but not the popup window that appears when the annotation is * opened. * * @return opacity value for nonstroking operations. Returns 1.0 (default value) if entry is not present */ public float getNonStrokingOpacity() { PdfNumber nonStrokingOpacity = getPdfObject().getAsNumber(PdfName.ca); return nonStrokingOpacity != null ? nonStrokingOpacity.floatValue() : 1; } /** * PDF 2.0. When regenerating the annotation's appearance stream, this is the * opacity value that shall be used for all nonstroking * operations on all visible elements of the annotation in its closed state (including its * background and border) but not the popup window that appears when the annotation is * opened. * * @param nonStrokingOpacity opacity for nonstroking operations * @return this {@link PdfAnnotation} instance */ public PdfAnnotation setNonStrokingOpacity(float nonStrokingOpacity) { return put(PdfName.ca, new PdfNumber(nonStrokingOpacity)); } /** * PDF 2.0. When regenerating the annotation's appearance stream, this is the * opacity value that shall be used for stroking all visible * elements of the annotation in its closed state, including its background and border, but * not the popup window that appears when the annotation is opened. * * @return opacity for stroking operations, including background and border */ public float getStrokingOpacity() { PdfNumber strokingOpacity = getPdfObject().getAsNumber(PdfName.CA); return strokingOpacity != null ? strokingOpacity.floatValue() : 1; } /** * PDF 2.0. When regenerating the annotation's appearance stream, this is the * opacity value that shall be used for stroking all visible * elements of the annotation in its closed state, including its background and border, but * not the popup window that appears when the annotation is opened. * * @param strokingOpacity opacity for stroking operations, including background and border * @return this {@link PdfAnnotation} object */ public PdfAnnotation setStrokingOpacity(float strokingOpacity) { return put(PdfName.CA, new PdfNumber(strokingOpacity)); } /** * Inserts the value into into the underlying {@link PdfDictionary} of this {@link PdfAnnotation} and associates it * with the specified key. If the key is already present in this {@link PdfAnnotation}, this method will override * the old value with the specified one. * * @param key key to insert or to override * @param value the value to associate with the specified key * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation put(PdfName key, PdfObject value) { getPdfObject().put(key, value); setModified(); return this; } /** * Removes the specified key from the underlying {@link PdfDictionary} of this {@link PdfAnnotation}. * * @param key key to be removed * @return this {@link PdfAnnotation} instance. */ public PdfAnnotation remove(PdfName key) { getPdfObject().remove(key); return this; } /** *

* Adds file associated with PDF annotation and identifies the relationship between them. *

* Associated files may be used in Pdf/A-3 and Pdf 2.0 documents. * The method adds file to array value of the AF key in the annotation dictionary. *

* For associated files their associated file specification dictionaries shall include the AFRelationship key * * @param fs file specification dictionary of associated file */ public void addAssociatedFile(PdfFileSpec fs) { if (null == ((PdfDictionary) fs.getPdfObject()).get(PdfName.AFRelationship)) { Logger logger = LoggerFactory.getLogger(PdfAnnotation.class); logger.error(IoLogMessageConstant.ASSOCIATED_FILE_SPEC_SHALL_INCLUDE_AFRELATIONSHIP); } PdfArray afArray = getPdfObject().getAsArray(PdfName.AF); if (afArray == null) { afArray = new PdfArray(); put(PdfName.AF, afArray); } afArray.add(fs.getPdfObject()); } /** * Returns files associated with PDF annotation. * * @param create defines whether AF arrays will be created if it doesn't exist * @return associated files array */ public PdfArray getAssociatedFiles(boolean create) { PdfArray afArray = getPdfObject().getAsArray(PdfName.AF); if (afArray == null && create) { afArray = new PdfArray(); put(PdfName.AF, afArray); } return afArray; } /** * To manually flush a {@code PdfObject} behind this wrapper, you have to ensure * that this object is added to the document, i.e. it has an indirect reference. * Basically this means that before flushing you need to explicitly call {@link #makeIndirect(PdfDocument)}. * For example: wrapperInstance.makeIndirect(document).flush(); * Note that not every wrapper require this, only those that have such warning in documentation. */ @Override public void flush() { super.flush(); } @Override protected boolean isWrappedObjectMustBeIndirect() { return true; } // Created as a private static class in order to facilitate autoport. static class PdfUnknownAnnotation extends PdfAnnotation { protected PdfUnknownAnnotation(PdfDictionary pdfObject) { super(pdfObject); } @Override public PdfName getSubtype() { return getPdfObject().getAsName(PdfName.Subtype); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy