aboutsummaryrefslogtreecommitdiffstats
path: root/poi-ooxml
diff options
context:
space:
mode:
authorPJ Fanning <fanningpj@apache.org>2022-11-16 22:10:18 +0000
committerPJ Fanning <fanningpj@apache.org>2022-11-16 22:10:18 +0000
commit09126e404cbe4ca07987d858634c05bbebf07c07 (patch)
treeb8f362a30edf898017da5e9cd6c3d81c3787bee7 /poi-ooxml
parentf0e4703f04a85d3f97cbee314d76310b9dcd700f (diff)
downloadpoi-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')
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java35
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java6
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTheme.java185
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java2
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