From commits-return-11892-archive-asf-public=cust-asf.ponee.io@poi.apache.org Sun Dec 16 15:55:27 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id ED79A180625 for ; Sun, 16 Dec 2018 15:55:25 +0100 (CET) Received: (qmail 49275 invoked by uid 500); 16 Dec 2018 14:55:24 -0000 Mailing-List: contact commits-help@poi.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@poi.apache.org Delivered-To: mailing list commits@poi.apache.org Received: (qmail 49266 invoked by uid 99); 16 Dec 2018 14:55:24 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 16 Dec 2018 14:55:24 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 20B4C3A008F for ; Sun, 16 Dec 2018 14:55:24 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1849030 - in /poi: site/src/documentation/content/xdocs/ trunk/ trunk/sonar/ trunk/sonar/ooxml/ trunk/src/java/org/apache/poi/sl/usermodel/ trunk/src/ooxml/java/org/apache/poi/xslf/draw/ trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/ ... Date: Sun, 16 Dec 2018 14:55:23 -0000 To: commits@poi.apache.org From: kiwiwings@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20181216145524.20B4C3A008F@svn01-us-west.apache.org> Author: kiwiwings Date: Sun Dec 16 14:55:23 2018 New Revision: 1849030 URL: http://svn.apache.org/viewvc?rev=1849030&view=rev Log: #62365 - SVG image support in XSLF Added: poi/trunk/src/ooxml/java/org/apache/poi/xslf/draw/ poi/trunk/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java (with props) Modified: poi/site/src/documentation/content/xdocs/changes.xml poi/trunk/build.gradle poi/trunk/build.xml poi/trunk/sonar/ooxml/pom.xml poi/trunk/sonar/pom.xml poi/trunk/src/java/org/apache/poi/sl/usermodel/PictureData.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRelation.java poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java Modified: poi/site/src/documentation/content/xdocs/changes.xml URL: http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/changes.xml?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/site/src/documentation/content/xdocs/changes.xml (original) +++ poi/site/src/documentation/content/xdocs/changes.xml Sun Dec 16 14:55:23 2018 @@ -87,6 +87,7 @@ + SVG image support in XSLF"/> Multiple digital signature in excel file broke first signature"/> IBM JDK JIT causes AIOOBE in TexturePaintContext"/> IBM JCE workarounds Modified: poi/trunk/build.gradle URL: http://svn.apache.org/viewvc/poi/trunk/build.gradle?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/trunk/build.gradle (original) +++ poi/trunk/build.gradle Sun Dec 16 14:55:23 2018 @@ -91,7 +91,7 @@ subprojects { // See https://github.com/melix/japicmp-gradle-plugin apply plugin: 'me.champeau.gradle.japicmp' - version = '4.0.1-SNAPSHOT' + version = '4.0.2-SNAPSHOT' ext { japicmpversion = '4.0.0' } @@ -233,6 +233,11 @@ project('ooxml') { compile 'org.bouncycastle:bcpkix-jdk15on:1.60' compile 'com.github.virtuald:curvesapi:1.05' + // compile only, don't add it to our dist as it blows up the size + compile 'org.apache.xmlgraphics:batik-all:1.10' + compile 'xml-apis:xml-apis-ext:1.3.04' + compile 'org.apache.xmlgraphics:xmlgraphics-commons:2.3' + // for ooxml-lite, should we move this somewhere else? compile 'junit:junit:4.12' Modified: poi/trunk/build.xml URL: http://svn.apache.org/viewvc/poi/trunk/build.xml?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/trunk/build.xml (original) +++ poi/trunk/build.xml Sun Dec 16 14:55:23 2018 @@ -217,6 +217,14 @@ under the License. + + + + + + + + + + + + + + @@ -402,11 +416,13 @@ under the License. + + @@ -777,6 +793,9 @@ under the License. + + + @@ -791,6 +810,9 @@ under the License. + + + @@ -932,6 +954,7 @@ under the License. + typeLoader; @@ -944,7 +967,7 @@ under the License. return stl; } - public static \2 newInstance\(\) \{]]> + public static \2 newInstance\(\) \{]]> Modified: poi/trunk/sonar/ooxml/pom.xml URL: http://svn.apache.org/viewvc/poi/trunk/sonar/ooxml/pom.xml?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/trunk/sonar/ooxml/pom.xml (original) +++ poi/trunk/sonar/ooxml/pom.xml Sun Dec 16 14:55:23 2018 @@ -185,5 +185,12 @@ 1.19 test + + + + org.apache.xmlgraphics + batik-all + 1.10 + Modified: poi/trunk/sonar/pom.xml URL: http://svn.apache.org/viewvc/poi/trunk/sonar/pom.xml?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/trunk/sonar/pom.xml (original) +++ poi/trunk/sonar/pom.xml Sun Dec 16 14:55:23 2018 @@ -268,9 +268,7 @@ - - + typeLoader; @@ -283,25 +281,26 @@ return stl; } - public static \2 newInstance\(\) \{]]> + public static \2 newInstance\(\) \{]]> + + - + - + + org.apache.xmlbeans.XmlBeans.getContextTypeLoader getTypeLoader - + + Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/PictureData.java URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/PictureData.java?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/trunk/src/java/org/apache/poi/sl/usermodel/PictureData.java (original) +++ poi/trunk/src/java/org/apache/poi/sl/usermodel/PictureData.java Sun Dec 16 14:55:23 2018 @@ -46,7 +46,10 @@ public interface PictureData { /** WordPerfect graphics (.wpg) */ WPG(-1,12,"image/x-wpg",".wpg"), /** Microsoft Windows Media Photo image (.wdp) */ - WDP(-1,13,"image/vnd.ms-photo",".wdp"); + WDP(-1,13,"image/vnd.ms-photo",".wdp"), + /** Scalable vector graphics (.svg) - supported by Office 2016 and higher */ + SVG(-1, -1, "image/svg+xml", ".svg") + ; public final int nativeId, ooxmlId; public final String contentType,extension; Added: poi/trunk/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java?rev=1849030&view=auto ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java (added) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java Sun Dec 16 14:55:23 2018 @@ -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; + } +} Propchange: poi/trunk/src/ooxml/java/org/apache/poi/xslf/draw/SVGImageRenderer.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java Sun Dec 16 14:55:23 2018 @@ -218,6 +218,8 @@ public final class XSLFPictureData exten 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 exten 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; } } Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java?rev=1849030&r1=1849029&r2=1849030&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java Sun Dec 16 14:55:23 2018 @@ -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 XS implements PictureShape { 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 XS 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