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

com.vladsch.flexmark.docx.converter.util.BinaryPartAbstractImage Maven / Gradle / Ivy

package com.vladsch.flexmark.docx.converter.util;

import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.docx4j.UnitsOfMeasurement;
import org.docx4j.XmlUtils;
import org.docx4j.dml.Graphic;
import org.docx4j.dml.wordprocessingDrawing.Anchor;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.model.structure.PageDimensions;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.openpackaging.Base;
import org.docx4j.openpackaging.contenttype.ContentType;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.OpcPackage;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.ExternalTarget;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.PartName;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.CxCy;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBElement;
import java.awt.geom.Dimension2D;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;

public class BinaryPartAbstractImage {
    final org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage myAbstractImage;
    protected static Logger log = LoggerFactory.getLogger(org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.class);

    public BinaryPartAbstractImage(org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage abstractImage) {
        myAbstractImage = abstractImage;
    }

    /**
     * Create a <wp:inline> element suitable for this image,
     * which can be linked or embedded in w:p/w:r/w:drawing.
     * If the image is wider than the page, it will be scaled
     * automatically.
     *
     * @param filenameHint Any text, for example the original filename
     * @param altText      Like HTML's alt text
     * @param id1          An id unique in the document
     * @param id2          Another id unique in the document
     * @param link         true if this is to be linked not embedded
     *                     None of these things seem to be exposed in Word 2007's
     *                     user interface, but Word won't open the document if
     *                     any of the attributes these go in (except @ desc) aren't present!
     * @param posHOffset   offset from column, {@link Long#MAX_VALUE} for right aligned, {@link Long#MIN_VALUE} for left aligned, {@link Long#MAX_VALUE}/2 for centered
     * @param posVOffset   offset from paragraph
     * @return anchor element
     * @throws Exception throws exceptions on failure
     */
    public Anchor createImageAnchor(
            String filenameHint, String altText,
            int id1, int id2, boolean link, long posHOffset, long posVOffset
    ) throws Exception {

        WordprocessingMLPackage wmlPackage = ((WordprocessingMLPackage) myAbstractImage.getPackage());

        List sections = wmlPackage.getDocumentModel().getSections();
        PageDimensions page = sections.get(sections.size() - 1).getPageDimensions();

        CxCy cxcy = CxCy.scale(myAbstractImage.getImageInfo(), page);

        return createImageAnchor(filenameHint, altText,
                id1, id2, cxcy.getCx(), cxcy.getCy(), link, posHOffset, posVOffset);
    }

    /**
     * @param filenameHint file name hint
     * @param altText      description
     * @param id1          <wp:docPr id
     * @param id2          <pic:cNvPr id
     * @param link         true if to link, else embed
     * @param maxWidth     max width of image
     * @param maxHeight    max height of image
     * @param posHOffset   offset from column, {@link Long#MAX_VALUE} for right aligned, {@link Long#MIN_VALUE} for left aligned, {@link Long#MAX_VALUE}/2 for centered
     * @param posVOffset   offset from paragraph
     * @return anchor element
     * @throws Exception throws exceptions on failure
     */
    public Anchor createImageAnchor(
            String filenameHint, String altText,
            int id1, int id2, boolean link, int maxWidth, int maxHeight, long posHOffset, long posVOffset
    ) throws Exception {

        // This signature can scale the image to specified maxWidth

        WordprocessingMLPackage wmlPackage = ((WordprocessingMLPackage) this.getPackage());

        List sections = wmlPackage.getDocumentModel().getSections();
        PageDimensions page = sections.get(sections.size() - 1).getPageDimensions();

        CxCy cxcy = scale(myAbstractImage.getImageInfo(), page, maxWidth, maxHeight);

        return createImageAnchor(filenameHint, altText, id1, id2, cxcy.getCx(), cxcy.getCy(), link, posHOffset, posVOffset);
    }

    /**
     * Return scaling values constrained by specified maxWidth/maxHeight.
     * Useful if the image is to be inserted into a table cell of known width.
     *
     * @param imageInfo image info
     * @param page      page dimensions
     * @param maxWidth  max width
     * @param maxHeight max height
     * @return cx cy sizes
     * @since 3.3.0
     */
    public static CxCy scale(ImageInfo imageInfo, PageDimensions page, int maxWidth, int maxHeight) {

        double writableWidthTwips = page.getWritableWidthTwips();
        log.debug("writableWidthTwips: " + writableWidthTwips);

        if (maxWidth > 0 && maxWidth < writableWidthTwips) {
            writableWidthTwips = maxWidth;
            log.debug("reduced to: " + writableWidthTwips);
        }

        double writableHeightTwips = page.getWritableHeightTwips();
        log.debug("writableHeightTwips: " + writableHeightTwips);

        if (maxHeight > 0 && maxHeight < writableHeightTwips) {
            writableHeightTwips = maxHeight;
            log.debug("reduced to: " + writableHeightTwips);
        }

        ImageSize size = imageInfo.getSize();

        // get image size in pixels
        Dimension2D dpx = size.getDimensionPx();

        // convert pixels to twips (uses configured DPI setting - NOT the
        // image DPI)
        double imageWidthTwips = UnitsOfMeasurement.pxToTwipDouble(dpx.getWidth());
        double imageHeightTwips = UnitsOfMeasurement.pxToTwipDouble(dpx.getHeight());

        log.debug("imageWidthTwips: " + imageWidthTwips);
        log.debug("imageHeightTwips: " + imageHeightTwips);

        long cx;
        long cy;
        boolean scaled = false;
        if (imageWidthTwips > writableWidthTwips && imageHeightTwips > writableHeightTwips) {
            log.debug("Scaling image to fit page width/height");
            scaled = true;

            double scale = Math.min(writableWidthTwips / imageWidthTwips, writableHeightTwips / imageHeightTwips);

            cx = UnitsOfMeasurement.twipToEMU(imageWidthTwips * scale);
            cy = UnitsOfMeasurement.twipToEMU(imageHeightTwips * scale);
        } else if (imageWidthTwips > writableWidthTwips) {
            log.debug("Scaling image to fit page width");
            scaled = true;

            cx = UnitsOfMeasurement.twipToEMU(writableWidthTwips);
            cy = UnitsOfMeasurement.twipToEMU(imageHeightTwips * writableWidthTwips / imageWidthTwips);
        } else if (imageHeightTwips > writableHeightTwips) {
            log.debug("Scaling image to fit page height");
            scaled = true;

            cx = UnitsOfMeasurement.twipToEMU(imageWidthTwips * writableHeightTwips / imageHeightTwips);
            cy = UnitsOfMeasurement.twipToEMU(writableHeightTwips);
        } else {
            log.debug("Scaling image - not necessary");

            cx = UnitsOfMeasurement.twipToEMU(imageWidthTwips);
            cy = UnitsOfMeasurement.twipToEMU(imageHeightTwips);
        }

        log.debug("cx=" + cx + "; cy=" + cy);

        return CxCy.scaleToFit(UnitsOfMeasurement.twipToEMU(imageWidthTwips), UnitsOfMeasurement.twipToEMU(imageHeightTwips), cx, cy);
    }

    /**
     * Create a <wp:inline> element suitable for this image,
     * which can be _embedded_ in w:p/w:r/w:drawing.
     *
     * @param filenameHint Any text, for example the original filename
     * @param altText      Like HTML's alt text
     * @param id1          <wp:docPr id
     * @param id2          <pic:cNvPr id
     * @param cx           Image width in twip
     * @param link         true if this is to be linked not embedded
     *                     None of these things seem to be exposed in Word 2007's
     *                     user interface, but Word won't open the document if
     *                     any of the attributes these go in (except @ desc) aren't present!
     * @param posHOffset   offset from column, {@link Long#MAX_VALUE} for right aligned, {@link Long#MIN_VALUE} for left aligned, {@link Long#MAX_VALUE}/2 for centered
     * @param posVOffset   offset from paragraph
     * @return anchor element
     * @throws Exception throws exceptions on failure
     */
    public Anchor createImageAnchor(
            String filenameHint, String altText,
            int id1, int id2, long cx, boolean link, long posHOffset, long posVOffset
    ) throws Exception {

        ImageSize size = myAbstractImage.getImageInfo().getSize();

        Dimension2D dPt = size.getDimensionPt();
        double imageWidthTwips = dPt.getWidth() * 20;
        log.debug("imageWidthTwips: " + imageWidthTwips);

        long cy;

        log.debug("Scaling image height to retain aspect ratio");
        cy = UnitsOfMeasurement.twipToEMU(dPt.getHeight() * 20 * cx / imageWidthTwips);

        // Now convert cx to EMU
        cx = UnitsOfMeasurement.twipToEMU(cx);

        log.debug("cx=" + cx + "; cy=" + cy);

        return createImageAnchor(filenameHint, altText, id1, id2, cx, cy, link, posHOffset, posVOffset);
    }

    /**
     * Create a <wp:anchor> element suitable for this image, which can be
     * linked or embedded in w:p/w:r/w:drawing, specifying height and width.  Note
     * that you'd ordinarily use one of the methods which don't require
     * you to specify height (cy).
     *
     * @param filenameHint Any text, for example the original filename
     * @param altText      Like HTML's alt text
     * @param id1          <wp:docPr id
     * @param id2          <pic:cNvPr id
     * @param cx           Image width in EMU
     * @param cy           Image height in EMU
     * @param link         true if this is to be linked not embedded
     * @param posHOffset   offset from column, {@link Long#MAX_VALUE} for right aligned, {@link Long#MIN_VALUE} for left aligned, {@link Long#MAX_VALUE}/2 for centered
     * @param posVOffset   offset from paragraph
     * @return anchor element
     * @throws Exception throws exceptions on failure
     */
    public Anchor createImageAnchor(
            String filenameHint, String altText,
            int id1, int id2, long cx, long cy, boolean link,
            long posHOffset, long posVOffset
    ) throws Exception {

        // Floating - The drawing object is anchored within the text, but can be absolutely positioned in the
        // document relative to the page.

        if (filenameHint == null) {
            filenameHint = "";
        }
        if (altText == null) {
            altText = "";
        }

        String type;
        if (link) {
            type = "r:link";
        } else {
            type = "r:embed";
        }

        String alignmentNone = "" +
                "${posHOffset}" +
                "${posVOffset}" +
                "" +
                "";

        String alignmentLeft = "" +
                "\n" +
                "  left\n" +
                "\n" +
                "\n" +
                "  0\n" +
                "" +
                "\n" +
                "";

        String alignmentCenter = "" +
                "\n" +
                "  center\n" +
                "\n" +
                "\n" +
                "  0\n" +
                "" +
                "\n" +
                "";

        String alignmentRight = "" +
                "\n" +
                "  right\n" +
                "\n" +
                "\n" +
                "  0\n" +
                "" +
                "\n" +
                "";

        String mlTop =
                "" //  wp14:anchorId=\"28C768E3\" wp14:editId=\"050FA02A\">"
                        + ""
                        + ""
                        + ""  // b=4445
                        + ""
                        + ""
                        + " "
                        + " "
                        + ""
                        //		           + " "
                        + ""
                        + ""
                        + ""
                        //		      + "00"
                        + "";

        String mlBottom = ""
                + "";

        HashMap mappings = new HashMap<>();

        String ml;

        if (posHOffset == Long.MAX_VALUE) {
            ml = mlTop + alignmentRight + mlBottom;
        } else if (posHOffset == Long.MAX_VALUE / 2) {
            ml = mlTop + alignmentCenter + mlBottom;
        } else if (posHOffset == Long.MIN_VALUE) {
            ml = mlTop + alignmentLeft + mlBottom;
        } else {
            ml = mlTop + alignmentNone + mlBottom;
        }

        mappings.put("cx", Long.toString(cx));
        mappings.put("cy", Long.toString(cy));
        mappings.put("posHOffset", Long.toString(posHOffset));
        mappings.put("posVOffset", Long.toString(posVOffset));
        mappings.put("filenameHint", filenameHint);
        mappings.put("altText", altText);
        mappings.put("rEmbedId", myAbstractImage.getRelLast().getId());
        mappings.put("id1", Integer.toString(id1));
        mappings.put("id2", Integer.toString(id2));

        Object o = XmlUtils.unmarshallFromTemplate(ml, mappings);
        Anchor anchor = (Anchor) ((JAXBElement) o).getValue();

        return anchor;
    }

    final static String namespaces = " xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" "
            + "xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" "
            + "xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\"";

    /**
     * @param filenameHint Any text, for example the original filename
     * @param altText      Like HTML's alt text
     * @param id1          <wp:docPr id
     * @param id2          <pic:cNvPr id
     * @param link         true if this is to be linked not embedded
     * @param maxWidth     max width
     * @param maxHeight    max height
     * @return inline element
     * @throws Exception throws exceptions on failure
     * @since 3.3.0
     */
    public Inline createImageInline(
            String filenameHint, String altText,
            int id1, int id2, boolean link, int maxWidth, int maxHeight
    ) throws Exception {

        // This signature can scale the image to specified maxWidth and maxHeight

        WordprocessingMLPackage wmlPackage = ((WordprocessingMLPackage) this.getPackage());

        List sections = wmlPackage.getDocumentModel().getSections();
        PageDimensions page = sections.get(sections.size() - 1).getPageDimensions();
        ImageSize size = myAbstractImage.getImageInfo().getSize();

        CxCy cxcy = scale(myAbstractImage.getImageInfo(), page, maxWidth, maxHeight);

        return createImageInline(filenameHint, altText,
                id1, id2, cxcy.getCx(), cxcy.getCy(), link);
    }

    /**
     * Create an image part from the provided byte array, attach it to the source part
     * (eg the main document part, a header part etc), and return it.
     * 

* Works for both docx and pptx. *

* Note: this method creates a temp file (and attempts to delete it). * That's because it uses org.apache.xmlgraphics * * @param opcPackage package * @param sourcePart part * @param bytes image bytes * @return binary image * @throws Exception throws exceptions on failure */ public static BinaryPartAbstractImage createImagePart( OpcPackage opcPackage, Part sourcePart, byte[] bytes ) throws Exception { return new BinaryPartAbstractImage(org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(opcPackage, sourcePart, bytes)); } @Deprecated public ImageInfo getImageInfo() {return myAbstractImage.getImageInfo();} @Deprecated public void setImageInfo(ImageInfo imageInfo) {myAbstractImage.setImageInfo(imageInfo);} public List getRels() {return myAbstractImage.getRels();} public Relationship getRelLast() {return myAbstractImage.getRelLast();} public static void setDensity(int density) {org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.setDensity(density);} public static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage createImagePart(WordprocessingMLPackage wordMLPackage, byte[] bytes) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);} public static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage createImagePart(WordprocessingMLPackage wordMLPackage, File imageFile) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(wordMLPackage, imageFile);} @Deprecated public static String createImageName(Base sourcePart, String proposedRelId, String ext) {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImageName(sourcePart, proposedRelId, ext);} public static String createImageName(OpcPackage opcPackage, Base sourcePart, String proposedRelId, String ext) {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImageName(opcPackage, sourcePart, proposedRelId, ext);} @Deprecated public static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage createImagePart(OpcPackage opcPackage, Part sourcePart, byte[] bytes, String mime, String ext) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(opcPackage, sourcePart, bytes, mime, ext);} public static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage createImagePart(OpcPackage opcPackage, Part sourcePart, byte[] bytes, String mime) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(opcPackage, sourcePart, bytes, mime);} public static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage createImagePart(OpcPackage opcPackage, Part sourcePart, File imageFile) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createImagePart(opcPackage, sourcePart, imageFile);} public static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage createLinkedImagePart(WordprocessingMLPackage wordMLPackage, URL fileurl) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createLinkedImagePart(wordMLPackage, fileurl);} public static org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage createLinkedImagePart(OpcPackage opcPackage, Part sourcePart, URL url) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.createLinkedImagePart(opcPackage, sourcePart, url);} @Deprecated public Inline createImageInline(String filenameHint, String altText, int id1, int id2) throws Exception {return myAbstractImage.createImageInline(filenameHint, altText, id1, id2);} public Inline createImageInline(String filenameHint, String altText, int id1, int id2, boolean link) throws Exception {return myAbstractImage.createImageInline(filenameHint, altText, id1, id2, link);} public Inline createImageInline(String filenameHint, String altText, int id1, int id2, boolean link, int maxWidth) throws Exception {return myAbstractImage.createImageInline(filenameHint, altText, id1, id2, link, maxWidth);} @Deprecated public Inline createImageInline(String filenameHint, String altText, int id1, int id2, long cx) throws Exception {return myAbstractImage.createImageInline(filenameHint, altText, id1, id2, cx);} public Inline createImageInline(String filenameHint, String altText, int id1, int id2, long cx, boolean link) throws Exception {return myAbstractImage.createImageInline(filenameHint, altText, id1, id2, cx, link);} public Inline createImageInline(String filenameHint, String altText, int id1, int id2, long cx, long cy, boolean link) throws Exception {return myAbstractImage.createImageInline(filenameHint, altText, id1, id2, cx, cy, link);} public static ImageInfo getImageInfo(URL url) throws Exception {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.getImageInfo(url);} public static void main(String[] args) throws Exception {org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.main(args);} public static void displayImageInfo(ImageInfo info) {org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.displayImageInfo(info);} public static byte[] getImage(WordprocessingMLPackage wmlPkg, Graphic graphic) {return org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.getImage(wmlPkg, graphic);} public static void convertToPNG(InputStream is, OutputStream os, int density) throws IOException, InterruptedException {org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.convertToPNG(is, os, density);} public static void copy2(InputStream is, OutputStream os) throws IOException {org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.copy2(is, os);} public ExternalTarget getExternalTarget() {return myAbstractImage.getExternalTarget();} public void setBinaryData(InputStream binaryData) {myAbstractImage.setBinaryData(binaryData);} public void setBinaryData(byte[] bytes) {myAbstractImage.setBinaryData(bytes);} public void setBinaryData(ByteBuffer bb) {myAbstractImage.setBinaryData(bb);} public boolean isLoaded() {return myAbstractImage.isLoaded();} public ByteBuffer getBuffer() {return myAbstractImage.getBuffer();} public void writeDataToOutputStream(OutputStream out) throws IOException {myAbstractImage.writeDataToOutputStream(out);} public byte[] getBytes() {return myAbstractImage.getBytes();} public boolean isContentEqual(Part other) throws Docx4JException {return myAbstractImage.isContentEqual(other);} public List getSourceRelationships() {return myAbstractImage.getSourceRelationships();} @Deprecated public Relationship getSourceRelationship() {return myAbstractImage.getSourceRelationship();} @Deprecated public void setSourceRelationship(Relationship sourceRelationship) {myAbstractImage.setSourceRelationship(sourceRelationship);} public String getRelationshipType() {return myAbstractImage.getRelationshipType();} public void setRelationshipType(String relationshipType) {myAbstractImage.setRelationshipType(relationshipType);} @Deprecated public RelationshipsPart getOwningRelationshipPart() {return myAbstractImage.getOwningRelationshipPart();} @Deprecated public void setOwningRelationshipPart(RelationshipsPart owningRelationshipPart) {myAbstractImage.setOwningRelationshipPart(owningRelationshipPart);} public long getContentLengthAsLoaded() {return myAbstractImage.getContentLengthAsLoaded();} public OpcPackage getPackage() {return myAbstractImage.getPackage();} public void setPackage(OpcPackage pack) {myAbstractImage.setPackage(pack);} public boolean setPartShortcut(Part part, String relationshipType) {return myAbstractImage.setPartShortcut(part, relationshipType);} public void setVersion(long version) {myAbstractImage.setVersion(version);} public long getVersion() {return myAbstractImage.getVersion();} public void rename(PartName newName) {myAbstractImage.rename(newName);} public void remove() {myAbstractImage.remove();} public Object getUserData(String key) {return myAbstractImage.getUserData(key);} public void setUserData(String key, Object value) {myAbstractImage.setUserData(key, value);} public RelationshipsPart getRelationshipsPart() {return myAbstractImage.getRelationshipsPart();} public RelationshipsPart getRelationshipsPart(boolean createIfAbsent) {return myAbstractImage.getRelationshipsPart(createIfAbsent);} public void setRelationships(RelationshipsPart relationships) {myAbstractImage.setRelationships(relationships);} public String getContentType() {return myAbstractImage.getContentType();} public void setContentType(ContentType contentType) {myAbstractImage.setContentType(contentType);} public void setPartName(PartName partName) {myAbstractImage.setPartName(partName);} public PartName getPartName() {return myAbstractImage.getPartName();} public Relationship addTargetPart(Part targetpart, RelationshipsPart.AddPartBehaviour mode) throws InvalidFormatException {return myAbstractImage.addTargetPart(targetpart, mode);} public Relationship addTargetPart(Part targetpart) throws InvalidFormatException {return myAbstractImage.addTargetPart(targetpart);} public Relationship addTargetPart(Part targetpart, String proposedRelId) throws InvalidFormatException {return myAbstractImage.addTargetPart(targetpart, proposedRelId);} public Relationship addTargetPart(Part targetpart, RelationshipsPart.AddPartBehaviour mode, String proposedRelId) throws InvalidFormatException {return myAbstractImage.addTargetPart(targetpart, mode, proposedRelId);} public void reset() {myAbstractImage.reset();} }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy