diff options
author | PJ Fanning <fanningpj@apache.org> | 2022-11-16 22:10:18 +0000 |
---|---|---|
committer | PJ Fanning <fanningpj@apache.org> | 2022-11-16 22:10:18 +0000 |
commit | 09126e404cbe4ca07987d858634c05bbebf07c07 (patch) | |
tree | b8f362a30edf898017da5e9cd6c3d81c3787bee7 /poi-ooxml | |
parent | f0e4703f04a85d3f97cbee314d76310b9dcd700f (diff) | |
download | poi-09126e404cbe4ca07987d858634c05bbebf07c07.tar.gz poi-09126e404cbe4ca07987d858634c05bbebf07c07.zip |
[bug-66347] add XWPFTheme support to XWPFDocument. Thanks to Stephan Schwiebert.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1905344 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'poi-ooxml')
4 files changed, 227 insertions, 1 deletions
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java index 75b5cf06dd..af3a4d7beb 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java @@ -67,6 +67,7 @@ import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; +import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument; import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STOnOff1; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1; @@ -116,6 +117,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { protected XWPFEndnotes endnotes; protected XWPFNumbering numbering; protected XWPFStyles styles; + protected XWPFTheme theme; protected XWPFFootnotes footnotes; private CTDocument1 ctDocument; private XWPFSettings settings; @@ -242,6 +244,9 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { if (relation.equals(XWPFRelation.STYLES.getRelation())) { this.styles = (XWPFStyles) p; this.styles.onDocumentRead(); + } else if (relation.equals(XWPFRelation.THEME.getRelation())) { + this.theme = (XWPFTheme) p; + this.theme.onDocumentRead(); } else if (relation.equals(XWPFRelation.NUMBERING.getRelation())) { this.numbering = (XWPFNumbering) p; this.numbering.onDocumentRead(); @@ -459,6 +464,14 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { return footnotes.getFootnotesList(); } + /** + * @return Theme document (can be null) + * @since POI 5.2.4 + */ + public XWPFTheme getTheme() { + return theme; + } + public XWPFHyperlink[] getHyperlinks() { return hyperlinks.toArray(new XWPFHyperlink[0]); } @@ -1018,6 +1031,28 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { return styles; } + + /** + * Creates an empty styles for the document if one does not already exist + * + * @return styles + * @since POI 5.2.4 + */ + public XWPFTheme createTheme() { + if (theme == null) { + ThemeDocument themeDoc = ThemeDocument.Factory.newInstance(); + + XWPFRelation relation = XWPFRelation.THEME; + int i = getRelationIndex(relation); + + XWPFTheme wrapper = (XWPFTheme) createRelationship(relation, XWPFFactory.getInstance(), i); + wrapper.setTheme(themeDoc.addNewTheme()); + theme = wrapper; + } + + return theme; + } + /** * Creates an empty footnotes element for the document if one does not already exist * diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java index 7ae06d58da..074a941669 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java @@ -24,6 +24,7 @@ import org.apache.poi.common.usermodel.PictureType; import org.apache.poi.ooxml.POIXMLDocument; import org.apache.poi.ooxml.POIXMLRelation; import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; +import org.apache.poi.xssf.usermodel.XSSFRelation; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import static org.apache.poi.openxml4j.opc.PackageRelationshipTypes.HDPHOTO_PART; @@ -31,6 +32,8 @@ import static org.apache.poi.openxml4j.opc.PackageRelationshipTypes.IMAGE_PART; public final class XWPFRelation extends POIXMLRelation { + /* package */ static final String NS_DRAWINGML = XSSFRelation.NS_DRAWINGML; + /** * A map to lookup POIXMLRelation by its relation type */ @@ -116,7 +119,8 @@ public final class XWPFRelation extends POIXMLRelation { public static final XWPFRelation THEME = new XWPFRelation( "application/vnd.openxmlformats-officedocument.theme+xml", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", - "/word/theme/theme#.xml" + "/word/theme/theme#.xml", + XWPFTheme::new, XWPFTheme::new ); public static final XWPFRelation WORKBOOK = new XWPFRelation( diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTheme.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTheme.java new file mode 100644 index 0000000000..34ddce4e78 --- /dev/null +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTheme.java @@ -0,0 +1,185 @@ +/* ==================================================================== + 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.xwpf.usermodel; + +import org.apache.poi.ooxml.POIXMLDocumentPart; +import org.apache.poi.ooxml.POIXMLException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.util.Internal; +import org.apache.poi.xslf.usermodel.XSLFTheme; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlOptions; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles; +import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTColorScheme; +import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet; +import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; + +import javax.xml.namespace.QName; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; + +/** + * A shared style sheet in a .docx document + * + * @since POI 5.2.4 + */ +public class XWPFTheme extends POIXMLDocumentPart { + private CTOfficeStyleSheet _theme; + + /** + * Construct XWPFStyles from a package part + * + * @param part the package part holding the data of the styles + */ + public XWPFTheme(PackagePart part) { + super(part); + } + + /** + * Construct XWPFStyles from scratch for a new document. + */ + public XWPFTheme() { + _theme = CTOfficeStyleSheet.Factory.newInstance(); + } + + @SuppressWarnings("WeakerAccess") + public void importTheme(XSLFTheme theme) { + _theme = theme.getXmlObject(); + } + + /** + * + * @return name of this theme, e.g. "Office Theme" + */ + public String getName(){ + return _theme.getName(); + } + + /** + * Set name of this theme + * + * @param name name of this theme + */ + public void setName(String name){ + _theme.setName(name); + } + + /** + * Get a color from the theme's color scheme by name + * + * @return a theme color or <code>null</code> if not found + */ + @Internal + public CTColor getCTColor(String name) { + CTBaseStyles elems = _theme.getThemeElements(); + CTColorScheme scheme = (elems == null) ? null : elems.getClrScheme(); + return getMapColor(name, scheme); + } + + + private static CTColor getMapColor(String mapName, CTColorScheme scheme) { + if (mapName == null || scheme == null) { + return null; + } + switch (mapName) { + case "accent1": + return scheme.getAccent1(); + case "accent2": + return scheme.getAccent2(); + case "accent3": + return scheme.getAccent3(); + case "accent4": + return scheme.getAccent4(); + case "accent5": + return scheme.getAccent5(); + case "accent6": + return scheme.getAccent6(); + case "dk1": + return scheme.getDk1(); + case "dk2": + return scheme.getDk2(); + case "folHlink": + return scheme.getFolHlink(); + case "hlink": + return scheme.getHlink(); + case "lt1": + return scheme.getLt1(); + case "lt2": + return scheme.getLt2(); + default: + return null; + } + } + + /** + * @return typeface of the major font to use in a document. + * Typically the major font is used for heading areas of a document. + * + */ + @SuppressWarnings("WeakerAccess") + public String getMajorFont(){ + return _theme.getThemeElements().getFontScheme().getMajorFont().getLatin().getTypeface(); + } + + /** + * @return typeface of the minor font to use in a document. + * Typically the monor font is used for normal text or paragraph areas. + * + */ + @SuppressWarnings("WeakerAccess") + public String getMinorFont(){ + return _theme.getThemeElements().getFontScheme().getMinorFont().getLatin().getTypeface(); + } + + /** + * Read document + */ + @Override + protected void onDocumentRead() throws IOException { + ThemeDocument themeDoc; + try (InputStream is = getPackagePart().getInputStream()) { + themeDoc = ThemeDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); + setTheme(themeDoc.getTheme()); + } catch (XmlException e) { + throw new POIXMLException("Unable to read theme", e); + } + } + + @Override + protected void commit() throws IOException { + if (_theme == null) { + throw new IOException("Unable to write out theme that was never read in!"); + } + + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(XWPFRelation.NS_DRAWINGML, "theme")); + PackagePart part = getPackagePart(); + try (OutputStream out = part.getOutputStream()) { + _theme.save(out, xmlOptions); + } + } + + public void setTheme(CTOfficeStyleSheet theme) { + _theme = theme; + } +} diff --git a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java index 8d3fe70ae3..9756291e86 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java @@ -70,6 +70,8 @@ public final class TestXWPFDocument { assertNotNull(xml1.getDocument()); assertNotNull(xml1.getDocument().getBody()); assertNotNull(xml1.getStyle()); + assertNotNull(xml1.getTheme()); + assertEquals("Cambria", xml1.getTheme().getMajorFont()); } // Complex file |