diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2018-12-16 16:51:08 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2018-12-16 16:51:08 +0000 |
commit | abe662db86034a0676bc0160e0878fbecefef488 (patch) | |
tree | ae844a12de4aafedf5dd44c625c0b1703f668de1 /src/ooxml/java/org | |
parent | cda119e3b8d47bff4ff0b02ccb021d27e31b1aab (diff) | |
parent | a308c6467e7efa4ed128ce6424cbf34e02ae59ec (diff) | |
download | poi-abe662db86034a0676bc0160e0878fbecefef488.tar.gz poi-abe662db86034a0676bc0160e0878fbecefef488.zip |
merge trunkhemf
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hemf@1849036 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/ooxml/java/org')
9 files changed, 413 insertions, 60 deletions
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/DSigRelation.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/DSigRelation.java new file mode 100644 index 0000000000..707233b074 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/DSigRelation.java @@ -0,0 +1,62 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.dsig; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.poi.ooxml.POIXMLDocumentPart; +import org.apache.poi.ooxml.POIXMLRelation; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; + +public class DSigRelation extends POIXMLRelation { + /** + * A map to lookup POIXMLRelation by its relation type + */ + private static final Map<String, DSigRelation> _table = new HashMap<>(); + + public static final DSigRelation ORIGIN_SIGS = new DSigRelation( + ContentTypes.DIGITAL_SIGNATURE_ORIGIN_PART, + PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN, + "/_xmlsignatures/origin.sigs", null + ); + + public static final DSigRelation SIG = new DSigRelation( + ContentTypes.DIGITAL_SIGNATURE_XML_SIGNATURE_PART, + PackageRelationshipTypes.DIGITAL_SIGNATURE, + "/_xmlsignatures/sig#.xml", null + ); + + private DSigRelation(String type, String rel, String defaultName, Class<? extends POIXMLDocumentPart> cls) { + super(type, rel, defaultName, cls); + _table.put(rel, this); + } + + /** + * Get POIXMLRelation by relation type + * + * @param rel relation type, for example, + * <code>http://schemas.openxmlformats.org/officeDocument/2006/relationships/image</code> + * @return registered POIXMLRelation or null if not found + */ + public static DSigRelation getInstance(String rel) { + return _table.get(rel); + } + +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java index 8e276f896e..71a42ef9e1 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java @@ -174,6 +174,13 @@ public class SignatureConfig { */ private boolean updateConfigOnValidate = false; + /** + * if true, the signature is added to the existing signatures + * + * @since POI 4.0.2 + */ + private boolean allowMultipleSignatures = false; + /** * Inits and checks the config object. @@ -1008,4 +1015,25 @@ public class SignatureConfig { public void setUpdateConfigOnValidate(boolean updateConfigOnValidate) { this.updateConfigOnValidate = updateConfigOnValidate; } + + /** + * @return true, if multiple signatures can be attached + * + * @since POI 4.0.2 + */ + public boolean isAllowMultipleSignatures() { + return allowMultipleSignatures; + } + + /** + * Activate multiple signatures + * + * @param allowMultipleSignatures if true, the signature will be added, + * otherwise all existing signatures will be replaced by the current + * + * @since POI 4.0.2 + */ + public void setAllowMultipleSignatures(boolean allowMultipleSignatures) { + this.allowMultipleSignatures = allowMultipleSignatures; + } }
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java index 20c347d4d7..1cb6e3ca1d 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java @@ -59,7 +59,6 @@ import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo; import org.apache.jcp.xml.dsig.internal.dom.DOMSubTreeData; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.ContentTypes; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePartName; @@ -377,9 +376,8 @@ public class SignatureInfo implements SignatureConfigurable { xmlSignContext.setURIDereferencer(uriDereferencer); } - for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) { - xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue()); - } + signatureConfig.getNamespacePrefixes().forEach(xmlSignContext::putNamespacePrefix); + xmlSignContext.setDefaultNamespacePrefix(""); // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS)); @@ -516,9 +514,7 @@ public class SignatureInfo implements SignatureConfigurable { protected void writeDocument(Document document) throws MarshalException { XmlOptions xo = new XmlOptions(); Map<String,String> namespaceMap = new HashMap<>(); - for(Map.Entry<String,String> entry : signatureConfig.getNamespacePrefixes().entrySet()){ - namespaceMap.put(entry.getValue(), entry.getKey()); - } + signatureConfig.getNamespacePrefixes().forEach((k,v) -> namespaceMap.put(v,k)); xo.setSaveSuggestedPrefixes(namespaceMap); xo.setUseDefaultNamespace(); @@ -530,43 +526,58 @@ public class SignatureInfo implements SignatureConfigurable { */ OPCPackage pkg = signatureConfig.getOpcPackage(); - PackagePartName sigPartName, sigsPartName; try { - // <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/> - sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig1.xml"); // <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/> - sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs"); - } catch (InvalidFormatException e) { - throw new MarshalException(e); - } + final DSigRelation originDesc = DSigRelation.ORIGIN_SIGS; + PackagePartName originPartName = PackagingURIHelper.createPartName(originDesc.getFileName(0)); + + PackagePart originPart = pkg.getPart(originPartName); + if (originPart == null) { + // touch empty marker file + originPart = pkg.createPart(originPartName, originDesc.getContentType()); + pkg.addRelationship(originPartName, TargetMode.INTERNAL, originDesc.getRelation()); + } - PackagePart sigPart = pkg.getPart(sigPartName); - if (sigPart == null) { - sigPart = pkg.createPart(sigPartName, ContentTypes.DIGITAL_SIGNATURE_XML_SIGNATURE_PART); - } + // <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/> + final DSigRelation sigDesc = DSigRelation.SIG; + int nextSigIdx = pkg.getUnusedPartIndex(sigDesc.getDefaultFileName()); + + if (!signatureConfig.isAllowMultipleSignatures()) { + PackageRelationshipCollection prc = originPart.getRelationshipsByType(sigDesc.getRelation()); + for (int i=2; i<nextSigIdx; i++) { + PackagePartName pn = PackagingURIHelper.createPartName(sigDesc.getFileName(i)); + for (PackageRelationship rel : prc) { + PackagePart pp = originPart.getRelatedPart(rel); + if (pp.getPartName().equals(pn)) { + originPart.removeRelationship(rel.getId()); + prc.removeRelationship(rel.getId()); + break; + } + } - try { - OutputStream os = sigPart.getOutputStream(); - SignatureDocument sigDoc = SignatureDocument.Factory.parse(document, DEFAULT_XML_OPTIONS); - sigDoc.save(os, xo); - os.close(); - } catch (Exception e) { - throw new MarshalException("Unable to write signature document", e); - } + pkg.removePart(pkg.getPart(pn)); + } + nextSigIdx = 1; + } - PackagePart sigsPart = pkg.getPart(sigsPartName); - if (sigsPart == null) { - // touch empty marker file - sigsPart = pkg.createPart(sigsPartName, ContentTypes.DIGITAL_SIGNATURE_ORIGIN_PART); - } - PackageRelationshipCollection relCol = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN); - for (PackageRelationship pr : relCol) { - pkg.removeRelationship(pr.getId()); - } - pkg.addRelationship(sigsPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN); + PackagePartName sigPartName = PackagingURIHelper.createPartName(sigDesc.getFileName(nextSigIdx)); + PackagePart sigPart = pkg.getPart(sigPartName); + if (sigPart == null) { + sigPart = pkg.createPart(sigPartName, sigDesc.getContentType()); + originPart.addRelationship(sigPartName, TargetMode.INTERNAL, sigDesc.getRelation()); + } else { + sigPart.clear(); + } + + try (OutputStream os = sigPart.getOutputStream()) { + SignatureDocument sigDoc = SignatureDocument.Factory.parse(document, DEFAULT_XML_OPTIONS); + sigDoc.save(os, xo); + } - sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE); + } catch (Exception e) { + throw new MarshalException("Unable to write signature document", e); + } } private Element getDsigElement(final Document document, final String localName) { diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java index 81e5b21971..e68b7a72d0 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java @@ -185,9 +185,7 @@ public class SignaturePart { final Map<String,String> nsMap = new HashMap<>(); { - for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) { - nsMap.put(me.getValue(), me.getKey()); - } + signatureConfig.getNamespacePrefixes().forEach((k,v) -> nsMap.put(v,k)); nsMap.put("dsss", MS_DIGSIG_NS); nsMap.put("ds", XML_DIGSIG_NS); } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java index b3bfe9ecfb..e7797e942d 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java @@ -129,10 +129,8 @@ public class KeyInfoSignatureFacet extends SignatureFacet { DOMSignContext domSignContext = (nextSibling == null) ? new DOMSignContext(key, n) : new DOMSignContext(key, n, nextSibling); - for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) { - domSignContext.putNamespacePrefix(me.getKey(), me.getValue()); - } - + signatureConfig.getNamespacePrefixes().forEach(domSignContext::putNamespacePrefix); + DOMStructure domStructure = new DOMStructure(n); domKeyInfo.marshal(domStructure, domSignContext); diff --git a/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java b/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java new file mode 100644 index 0000000000..2a03dda691 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java @@ -0,0 +1,136 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xslf.draw; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; + +import org.apache.batik.anim.dom.SAXSVGDocumentFactory; +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.DocumentLoader; +import org.apache.batik.bridge.GVTBuilder; +import org.apache.batik.bridge.UserAgent; +import org.apache.batik.bridge.UserAgentAdapter; +import org.apache.batik.ext.awt.RenderingHintsKeyExt; +import org.apache.batik.ext.awt.image.renderable.ClipRable8Bit; +import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.util.XMLResourceDescriptor; +import org.apache.poi.sl.draw.ImageRenderer; +import org.w3c.dom.Document; + +public class SVGImageRenderer implements ImageRenderer { + private final GVTBuilder builder = new GVTBuilder(); + private final BridgeContext context; + private final SAXSVGDocumentFactory svgFact; + private GraphicsNode svgRoot; + private double alpha = 1.0; + + public SVGImageRenderer() { + String parser = XMLResourceDescriptor.getXMLParserClassName(); + // TOOO: tell the batik guys to use secure parsing feature + svgFact = new SAXSVGDocumentFactory(parser); + + UserAgent agent = new UserAgentAdapter(); + DocumentLoader loader = new DocumentLoader(agent); + context = new BridgeContext(agent, loader); + context.setDynamic(true); + } + + + @Override + public void loadImage(InputStream data, String contentType) throws IOException { + Document document = svgFact.createDocument("", data); + svgRoot = builder.build(context, document); + } + + @Override + public void loadImage(byte[] data, String contentType) throws IOException { + loadImage(new ByteArrayInputStream(data), contentType); + } + + @Override + public Dimension getDimension() { + Rectangle2D r = svgRoot.getPrimitiveBounds(); + return new Dimension((int)Math.ceil(r.getWidth()), (int)Math.ceil(r.getHeight())); + } + + @Override + public void setAlpha(double alpha) { + this.alpha = alpha; + } + + @Override + public BufferedImage getImage() { + return getImage(getDimension()); + } + + @Override + public BufferedImage getImage(Dimension dim) { + BufferedImage bi = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = (Graphics2D) bi.getGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2d.setRenderingHint(RenderingHintsKeyExt.KEY_BUFFERED_IMAGE, new WeakReference(bi)); + Dimension dimSVG = getDimension(); + + double scaleX = dim.getWidth() / dimSVG.getWidth(); + double scaleY = dim.getHeight() / dimSVG.getHeight(); + g2d.scale(scaleX, scaleY); + + svgRoot.paint(g2d); + g2d.dispose(); + + return bi; + } + + @Override + public boolean drawImage(Graphics2D graphics, Rectangle2D anchor) { + return drawImage(graphics, anchor, null); + } + + @Override + public boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip) { + if (clip == null) { + svgRoot.setClip(null); + } else { + Rectangle2D clippedRect = new Rectangle2D.Double( + anchor.getX()+clip.left, + anchor.getY()+clip.top, + anchor.getWidth()-(clip.left+clip.right), + anchor.getHeight()-(clip.top+clip.bottom) + ); + svgRoot.setClip(new ClipRable8Bit(null, clippedRect)); + } + + svgRoot.paint(graphics); + + return true; + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java index 881f5fc29b..b95b8ed356 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java @@ -218,6 +218,8 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture return PictureType.WDP; } else if (XSLFRelation.IMAGE_TIFF.getContentType().equals(ct)) { return PictureType.TIFF; + } else if (XSLFRelation.IMAGE_SVG.getContentType().equals(ct)) { + return PictureType.SVG; } else { return null; } @@ -237,6 +239,7 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture case WPG: return XSLFRelation.IMAGE_WPG; case WDP: return XSLFRelation.IMAGE_WDP; case TIFF: return XSLFRelation.IMAGE_TIFF; + case SVG: return XSLFRelation.IMAGE_SVG; default: return null; } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index 9f07b18bac..b8de623683 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -19,18 +19,31 @@ package org.apache.poi.xslf.usermodel; +import static org.apache.poi.openxml4j.opc.PackageRelationshipTypes.CORE_PROPERTIES_ECMA376_NS; + +import java.awt.Dimension; import java.awt.Insets; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.URI; +import javax.imageio.ImageIO; import javax.xml.namespace.QName; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.sl.usermodel.PictureData.PictureType; import org.apache.poi.sl.usermodel.PictureShape; import org.apache.poi.sl.usermodel.Placeholder; import org.apache.poi.util.Beta; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Units; +import org.apache.poi.xslf.draw.SVGImageRenderer; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; @@ -55,6 +68,11 @@ public class XSLFPictureShape extends XSLFSimpleShape implements PictureShape<XSLFShape,XSLFTextParagraph> { private static final POILogger LOG = POILogFactory.getLogger(XSLFPictureShape.class); + private static final String DML_NS = "http://schemas.microsoft.com/office/drawing/2010/main"; + private static final String SVG_NS = "http://schemas.microsoft.com/office/drawing/2016/SVG/main"; + private static final String BITMAP_URI = "{28A0092B-C50C-407E-A947-70E740481C1C}"; + private static final String SVG_URI = "{96DAC541-7B7A-43D3-8B79-37D633B846F1}"; + private XSLFPictureData _data; /*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) { @@ -196,6 +214,97 @@ public class XSLFPictureShape extends XSLFSimpleShape return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR()); } + /** + * Add a SVG image reference + * @param svgPic a previously imported svg image + */ + public void setSvgImage(XSLFPictureData svgPic) { + CTBlip blip = getBlip(); + CTOfficeArtExtensionList extLst = blip.isSetExtLst() ? blip.getExtLst() : blip.addNewExtLst(); + + final int bitmapId = getExt(extLst, BITMAP_URI); + CTOfficeArtExtension extBitmap; + if (bitmapId == -1) { + extBitmap = extLst.addNewExt(); + extBitmap.setUri(BITMAP_URI); + XmlCursor cur = extBitmap.newCursor(); + cur.toEndToken(); + cur.beginElement(new QName(DML_NS, "useLocalDpi", "a14")); + cur.insertNamespace("a14", DML_NS); + cur.insertAttributeWithValue("val", "0"); + cur.dispose(); + } + + final int svgId = getExt(extLst, SVG_URI);; + if (svgId != -1) { + extLst.removeExt(svgId); + } + + String svgRelId = getSheet().getRelationId(svgPic); + if (svgRelId == null) { + svgRelId = getSheet().addRelation(null, XSLFRelation.IMAGE_SVG, svgPic).getRelationship().getId(); + } + + CTOfficeArtExtension svgBitmap = extLst.addNewExt(); + svgBitmap.setUri(SVG_URI); + XmlCursor cur = svgBitmap.newCursor(); + cur.toEndToken(); + cur.beginElement(new QName(SVG_NS, "svgBlip", "asvg")); + cur.insertNamespace("asvg", SVG_NS); + cur.insertAttributeWithValue(new QName(CORE_PROPERTIES_ECMA376_NS, "embed", "rel"), svgRelId); + cur.dispose(); + } + + /** + * Convienence method for adding SVG images, which generates the preview image + * @param sheet the sheet to add + * @param svgPic the svg picture to add + * @param previewType the preview picture type or null (defaults to PNG) - currently only JPEG,GIF,PNG are allowed + * @param anchor the image anchor (for calculating the preview image size) or + * null (the preview size is taken from the svg picture bounds) + */ + public static XSLFPictureShape addSvgImage(XSLFSheet sheet, XSLFPictureData svgPic, PictureType previewType, Rectangle2D anchor) throws IOException { + + SVGImageRenderer renderer = new SVGImageRenderer(); + try (InputStream is = svgPic.getInputStream()) { + renderer.loadImage(is, svgPic.getType().contentType); + } + + Dimension dim = renderer.getDimension(); + Rectangle2D anc = (anchor != null) ? anchor + : new Rectangle2D.Double(0,0, Units.pixelToPoints((int)dim.getWidth()), Units.pixelToPoints((int)dim.getHeight())); + + PictureType pt = (previewType != null) ? previewType : PictureType.PNG; + if (pt != PictureType.JPEG || pt != PictureType.GIF || pt != PictureType.PNG) { + pt = PictureType.PNG; + } + + BufferedImage thmBI = renderer.getImage(dim); + ByteArrayOutputStream bos = new ByteArrayOutputStream(100000); + // use extension instead of enum name, because of "jpeg" + ImageIO.write(thmBI, pt.extension.substring(1), bos); + + XSLFPictureData pngPic = sheet.getSlideShow().addPicture(new ByteArrayInputStream(bos.toByteArray()), pt); + + XSLFPictureShape shape = sheet.createPicture(pngPic); + shape.setAnchor(anc); + shape.setSvgImage(svgPic); + return shape; + } + + + private int getExt(CTOfficeArtExtensionList extLst, String uri) { + final int size = extLst.sizeOfExtArray(); + for (int i=0; i<size; i++) { + CTOfficeArtExtension ext = extLst.getExtArray(i); + if (uri.equals(ext.getUri())) { + return i; + } + } + return -1; + } + + @Override void copy(XSLFShape sh){ super.copy(sh); @@ -219,11 +328,11 @@ public class XSLFPictureShape extends XSLFSimpleShape nvPr.unsetCustDataLst(); } if(blip.isSetExtLst()) { - + // TODO: check for SVG copying CTOfficeArtExtensionList extLst = blip.getExtLst(); //noinspection deprecation for(CTOfficeArtExtension ext : extLst.getExtArray()){ - String xpath = "declare namespace a14='http://schemas.microsoft.com/office/drawing/2010/main' $this//a14:imgProps/a14:imgLayer"; + String xpath = "declare namespace a14='"+ DML_NS +"' $this//a14:imgProps/a14:imgLayer"; XmlObject[] obj = ext.selectPath(xpath); if(obj != null && obj.length == 1){ XmlCursor c = obj[0].newCursor(); @@ -234,6 +343,5 @@ public class XSLFPictureShape extends XSLFSimpleShape } } } - } }
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java index 0ea5e34916..9b9fc9c844 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java @@ -16,6 +16,8 @@ ==================================================================== */ package org.apache.poi.xslf.usermodel; +import static org.apache.poi.openxml4j.opc.PackageRelationshipTypes.IMAGE_PART; + import java.util.HashMap; import java.util.Map; @@ -159,80 +161,87 @@ public final class XSLFRelation extends POIXMLRelation { public static final XSLFRelation IMAGE_EMF = new XSLFRelation( PictureType.EMF.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.emf", XSLFPictureData.class ); public static final XSLFRelation IMAGE_WMF = new XSLFRelation( PictureType.WMF.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.wmf", XSLFPictureData.class ); public static final XSLFRelation IMAGE_PICT = new XSLFRelation( PictureType.PICT.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.pict", XSLFPictureData.class ); public static final XSLFRelation IMAGE_JPEG = new XSLFRelation( PictureType.JPEG.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.jpeg", XSLFPictureData.class ); public static final XSLFRelation IMAGE_PNG = new XSLFRelation( PictureType.PNG.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.png", XSLFPictureData.class ); public static final XSLFRelation IMAGE_DIB = new XSLFRelation( PictureType.DIB.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.dib", XSLFPictureData.class ); public static final XSLFRelation IMAGE_GIF = new XSLFRelation( PictureType.GIF.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.gif", XSLFPictureData.class ); public static final XSLFRelation IMAGE_TIFF = new XSLFRelation( PictureType.TIFF.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.tiff", XSLFPictureData.class ); public static final XSLFRelation IMAGE_EPS = new XSLFRelation( PictureType.EPS.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.eps", XSLFPictureData.class ); public static final XSLFRelation IMAGE_BMP = new XSLFRelation( PictureType.BMP.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.bmp", XSLFPictureData.class ); public static final XSLFRelation IMAGE_WPG = new XSLFRelation( PictureType.WPG.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.wpg", XSLFPictureData.class ); public static final XSLFRelation IMAGE_WDP = new XSLFRelation( PictureType.WDP.contentType, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, "/ppt/media/image#.wdp", XSLFPictureData.class ); + public static final XSLFRelation IMAGE_SVG = new XSLFRelation( + PictureType.SVG.contentType, + IMAGE_PART, + "/ppt/media/image#.svg", + XSLFPictureData.class + ); + public static final XSLFRelation IMAGES = new XSLFRelation( null, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + IMAGE_PART, null, XSLFPictureData.class ); |