From c62002e7ba87b8b5755c409c8efa4b1f13958557 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Mon, 25 Jul 2022 09:25:05 +0000 Subject: [PATCH] refactor smart art code git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1903000 13f79535-47bb-0310-9956-ffa450edef68 --- .../examples/xslf/SmartArtConversionDemo.java | 5 +- .../src/main/java9/module-info.java | 18 +++- .../src/main/java9/module-info.java | 4 +- .../poi/xslf/usermodel/XSLFDiagram.java | 99 ++++++++++--------- .../poi/xslf/usermodel/XSLFTexturePaint.java | 15 +-- 5 files changed, 74 insertions(+), 67 deletions(-) diff --git a/poi-examples/src/main/java/org/apache/poi/examples/xslf/SmartArtConversionDemo.java b/poi-examples/src/main/java/org/apache/poi/examples/xslf/SmartArtConversionDemo.java index 56bc53d5b1..546711b507 100644 --- a/poi-examples/src/main/java/org/apache/poi/examples/xslf/SmartArtConversionDemo.java +++ b/poi-examples/src/main/java/org/apache/poi/examples/xslf/SmartArtConversionDemo.java @@ -77,9 +77,8 @@ public class SmartArtConversionDemo { CTBlipFillProperties blipFillProps = ctShape.getSpPr().getBlipFill(); CTBlip blip = blipFillProps.getBlip(); - // In SmartArt diagrams, the references to images/embeds are stored in drawing#.xml.rels. When read by - // POI it copies this relationship to the parent slide to allow POI to correctly resolve the images. - POIXMLDocumentPart inputPicturePart = diagram.getSheet().getRelationById(blip.getEmbed()); + // Relationships for SmartArt diagrams are stored in `drawing#.xml.rels`, not `slide#.xml.rels`. + POIXMLDocumentPart inputPicturePart = diagram.getDiagramDrawing().getRelationById(blip.getEmbed()); if (inputPicturePart == null || inputPicturePart.getPackagePart() == null) { continue; diff --git a/poi-ooxml-full/src/main/java9/module-info.java b/poi-ooxml-full/src/main/java9/module-info.java index f8e193e41e..6f47d1bd44 100644 --- a/poi-ooxml-full/src/main/java9/module-info.java +++ b/poi-ooxml-full/src/main/java9/module-info.java @@ -23,32 +23,44 @@ open module org.apache.poi.ooxml.schemas { requires java.xml; - - exports com.microsoft.schemas.compatibility; + exports com.microsoft.schemas.office.drawing.x2008.diagram; exports com.microsoft.schemas.office.excel; exports com.microsoft.schemas.office.office; + exports com.microsoft.schemas.office.powerpoint; + exports com.microsoft.schemas.office.spreadsheetml.x2018.threadedcomments; + exports com.microsoft.schemas.office.spreadsheetml.x2020.threadedcomments2; exports com.microsoft.schemas.office.visio.x2012.main; exports com.microsoft.schemas.office.word; + exports com.microsoft.schemas.office.word.x2021.wordml; exports com.microsoft.schemas.office.x2006.digsig; exports com.microsoft.schemas.vml; exports org.apache.poi.schemas.ooxml.system.ooxml; exports org.apache.poi.schemas.vmldrawing; exports org.etsi.uri.x01903.v13; + exports org.etsi.uri.x01903.v14; exports org.openxmlformats.schemas.drawingml.x2006.chart; + exports org.openxmlformats.schemas.drawingml.x2006.chartDrawing; + exports org.openxmlformats.schemas.drawingml.x2006.diagram; + exports org.openxmlformats.schemas.drawingml.x2006.lockedCanvas; exports org.openxmlformats.schemas.drawingml.x2006.main; exports org.openxmlformats.schemas.drawingml.x2006.picture; exports org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing; exports org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing; + exports org.openxmlformats.schemas.officeDocument.x2006.bibliography; + exports org.openxmlformats.schemas.officeDocument.x2006.characteristics; exports org.openxmlformats.schemas.officeDocument.x2006.customProperties; + exports org.openxmlformats.schemas.officeDocument.x2006.customXml; exports org.openxmlformats.schemas.officeDocument.x2006.docPropsVTypes; exports org.openxmlformats.schemas.officeDocument.x2006.extendedProperties; exports org.openxmlformats.schemas.officeDocument.x2006.math; exports org.openxmlformats.schemas.officeDocument.x2006.relationships; exports org.openxmlformats.schemas.officeDocument.x2006.sharedTypes; exports org.openxmlformats.schemas.presentationml.x2006.main; + exports org.openxmlformats.schemas.schemaLibrary.x2006.main; exports org.openxmlformats.schemas.spreadsheetml.x2006.main; exports org.openxmlformats.schemas.wordprocessingml.x2006.main; exports org.openxmlformats.schemas.xpackage.x2006.digitalSignature; + exports org.openxmlformats.schemas.xpackage.x2006.relationships; exports org.w3.x2000.x09.xmldsig; -} \ No newline at end of file +} diff --git a/poi-ooxml-lite/src/main/java9/module-info.java b/poi-ooxml-lite/src/main/java9/module-info.java index bca989c46b..69de73fa64 100644 --- a/poi-ooxml-lite/src/main/java9/module-info.java +++ b/poi-ooxml-lite/src/main/java9/module-info.java @@ -26,6 +26,7 @@ open module org.apache.poi.ooxml.schemas { exports com.microsoft.schemas.compatibility; + exports com.microsoft.schemas.office.drawing.x2008.diagram; exports com.microsoft.schemas.office.excel; exports com.microsoft.schemas.office.office; exports com.microsoft.schemas.office.visio.x2012.main; @@ -37,6 +38,7 @@ open module org.apache.poi.ooxml.schemas { exports org.etsi.uri.x01903.v13; exports org.etsi.uri.x01903.v14; exports org.openxmlformats.schemas.drawingml.x2006.chart; + exports org.openxmlformats.schemas.drawingml.x2006.diagram; exports org.openxmlformats.schemas.drawingml.x2006.main; exports org.openxmlformats.schemas.drawingml.x2006.picture; exports org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing; @@ -52,4 +54,4 @@ open module org.apache.poi.ooxml.schemas { exports org.openxmlformats.schemas.wordprocessingml.x2006.main; exports org.openxmlformats.schemas.xpackage.x2006.digitalSignature; exports org.w3.x2000.x09.xmldsig; -} \ No newline at end of file +} diff --git a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFDiagram.java b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFDiagram.java index a207f32dd3..f1073e31ce 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFDiagram.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFDiagram.java @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ + package org.apache.poi.xslf.usermodel; import com.microsoft.schemas.office.drawing.x2008.diagram.CTGroupShape; @@ -33,7 +34,6 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShapeNonVisual; import javax.xml.namespace.QName; import java.awt.geom.Rectangle2D; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; /** @@ -75,13 +75,12 @@ public class XSLFDiagram extends XSLFGraphicFrame { public static final String DRAWINGML_DIAGRAM_URI = "http://schemas.openxmlformats.org/drawingml/2006/diagram"; private final XSLFDiagramDrawing _drawing; - private final XSLFGroupShape _groupShape; - private final HashMap blipDocumentParts = new HashMap<>(); + private final XSLFDiagramGroupShape _groupShape; /* package protected */ XSLFDiagram(CTGraphicalObjectFrame shape, XSLFSheet sheet) { super(shape, sheet); _drawing = readDiagramDrawing(shape, sheet); - _groupShape = initGroupShape(sheet); + _groupShape = initGroupShape(); } private static boolean hasTextContent(CTShape msShapeCt) { @@ -95,14 +94,6 @@ public class XSLFDiagram extends XSLFGraphicFrame { .anyMatch(run -> run.getT() != null && !run.getT().trim().isEmpty()); } - private static boolean hasBlipEmbed(CTShape msShapeCt) { - return msShapeCt != null - && msShapeCt.getSpPr() != null - && msShapeCt.getSpPr().getBlipFill() != null - && msShapeCt.getSpPr().getBlipFill().getBlip() != null - && msShapeCt.getSpPr().getBlipFill().getBlip().getEmbed() != null; - } - private static XSLFDiagramDrawing readDiagramDrawing(CTGraphicalObjectFrame shape, XSLFSheet sheet) { CTGraphicalObjectData graphicData = shape.getGraphic().getGraphicData(); XmlObject[] children = graphicData.selectChildren(new QName(DRAWINGML_DIAGRAM_URI, "relIds")); @@ -130,8 +121,24 @@ public class XSLFDiagram extends XSLFGraphicFrame { return null; } + /** + * Returns the underlying {@link XSLFDiagramDrawing} used to create this diagram. + *

+ * NOTE: Modifying this drawing will not update the groupShape returned from {@link #getGroupShape()}. + */ + public XSLFDiagramDrawing getDiagramDrawing() { + return _drawing; + } + + /** + * Returns the diagram represented as a grouped shape. + */ + public XSLFDiagramGroupShape getGroupShape() { + return _groupShape; + } + // If the shape has text, two XSLFShapes are created. One shape element and one textbox element. - public List convertShape(CTShape msShapeCt) { + private List convertShape(CTShape msShapeCt) { org.openxmlformats.schemas.presentationml.x2006.main.CTShape shapeCt = org.openxmlformats.schemas.presentationml.x2006.main.CTShape.Factory.newInstance(); @@ -157,16 +164,6 @@ public class XSLFDiagram extends XSLFGraphicFrame { return shapes; } - private void mapDocumentParts(CTShape msShapeCt) { - if (hasBlipEmbed(msShapeCt)) { - String embedId = msShapeCt.getSpPr().getBlipFill().getBlip().getEmbed(); - POIXMLDocumentPart part = _drawing.getRelationById(embedId); - if (part != null) { - blipDocumentParts.put(embedId, part); - } - } - } - private org.openxmlformats.schemas.presentationml.x2006.main.CTShape convertText(CTShape msShapeCt, CTShapeNonVisual nonVisualCt) { org.openxmlformats.schemas.presentationml.x2006.main.CTShape textShapeCT = org.openxmlformats.schemas.presentationml.x2006.main.CTShape.Factory.newInstance(); @@ -187,16 +184,7 @@ public class XSLFDiagram extends XSLFGraphicFrame { return textShapeCT; } - /** - * Returns the underlying {@link XSLFDiagramDrawing} used to create this diagram. - *

- * NOTE: Modifying this drawing will not update the groupShape returned from {@link #getGroupShape()}. - */ - public XSLFDiagramDrawing getDiagramDrawing() { - return _drawing; - } - - private XSLFGroupShape initGroupShape(XSLFSheet sheet) { + private XSLFDiagramGroupShape initGroupShape() { XSLFDiagramDrawing drawing = getDiagramDrawing(); if (drawing == null || drawing.getDrawingDocument() == null) { return null; @@ -206,21 +194,10 @@ public class XSLFDiagram extends XSLFGraphicFrame { if (msGroupShapeCt == null || msGroupShapeCt.getSpList().isEmpty()) { return null; } - return convertMsGroupToGroupShape(msGroupShapeCt, sheet); + return convertMsGroupToGroupShape(msGroupShapeCt, drawing); } - /** - * Returns the diagram represented as a grouped shape. - */ - public XSLFGroupShape getGroupShape() { - return _groupShape; - } - - POIXMLDocumentPart getDocumentPart(String blipId) { - return blipDocumentParts.get(blipId); - } - - private XSLFGroupShape convertMsGroupToGroupShape(CTGroupShape msGroupShapeCt, XSLFSheet sheet) { + private XSLFDiagramGroupShape convertMsGroupToGroupShape(CTGroupShape msGroupShapeCt, XSLFDiagramDrawing drawing) { org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape groupShapeCt = org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape.Factory.newInstance(); @@ -233,17 +210,43 @@ public class XSLFDiagram extends XSLFGraphicFrame { for (CTShape msShapeCt : msGroupShapeCt.getSpList()) { List shapes = convertShape(msShapeCt); - mapDocumentParts(msShapeCt); groupShapeCt.getSpList().addAll(shapes); } Rectangle2D anchor = super.getAnchor(); Rectangle2D interiorAnchor = new Rectangle2D.Double(0, 0, anchor.getWidth(), anchor.getHeight()); - XSLFGroupShape groupShape = new XSLFGroupShape(groupShapeCt, getSheet()); + XSLFDiagramGroupShape groupShape = new XSLFDiagramGroupShape(groupShapeCt, getSheet(), drawing); groupShape.setAnchor(anchor); groupShape.setInteriorAnchor(interiorAnchor); groupShape.setRotation(super.getRotation()); return groupShape; } + + /** + * Simple wrapper around XSLFGroupShape to enable accessing underlying diagram relations correctly. + *

+ * Diagrams store relationships to media in `drawing#.xml.rels`. These relationships are accessible using + * {@link #getRelationById(String)}. + */ + static class XSLFDiagramGroupShape extends XSLFGroupShape { + + private XSLFDiagramDrawing diagramDrawing; + + protected XSLFDiagramGroupShape(org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape shape, + XSLFSheet sheet) { + super(shape, sheet); + } + + private XSLFDiagramGroupShape(org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape shape, + XSLFSheet sheet, + XSLFDiagramDrawing diagramDrawing) { + super(shape, sheet); + this.diagramDrawing = diagramDrawing; + } + + POIXMLDocumentPart getRelationById(String id) { + return diagramDrawing.getRelationById(id); + } + } } diff --git a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTexturePaint.java b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTexturePaint.java index 7e0c4050da..c0b1f1488d 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTexturePaint.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTexturePaint.java @@ -23,7 +23,6 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; -import java.util.stream.Collectors; import org.apache.poi.ooxml.POIXMLDocumentPart; import org.apache.poi.ooxml.util.POIXMLUnits; @@ -69,8 +68,9 @@ public class XSLFTexturePaint implements PaintStyle.TexturePaint { private PackagePart getPart() throws InvalidFormatException { String blipId = blip.getEmbed(); - for (XSLFDiagram diagram : extractDiagrams(sheet.getSlideShow())) { - POIXMLDocumentPart documentPart = diagram.getDocumentPart(blipId); + if (shape.getParent() != null && shape.getParent() instanceof XSLFDiagram.XSLFDiagramGroupShape) { + XSLFDiagram.XSLFDiagramGroupShape diagramGroupShape = (XSLFDiagram.XSLFDiagramGroupShape) shape.getParent(); + POIXMLDocumentPart documentPart = diagramGroupShape.getRelationById(blipId); if (documentPart != null) { return documentPart.getPackagePart(); } @@ -192,13 +192,4 @@ public class XSLFTexturePaint implements PaintStyle.TexturePaint { private static int getRectVal(Supplier isSet, Supplier val) { return isSet.get() ? POIXMLUnits.parsePercent(val.get()) : 0; } - - private static List extractDiagrams(XMLSlideShow slideShow) { - return slideShow.getSlides() - .stream() - .flatMap(s -> s.getShapes().stream()) - .filter(s -> s instanceof XSLFDiagram) - .map(s -> (XSLFDiagram) s) - .collect(Collectors.toList()); - } }