From d3de3636cfb3b6ae89b64069292b515bd2702a96 Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Sat, 21 Mar 2020 18:25:38 +0000 Subject: [PATCH] #64241 - XSLF - Wrong scheme colors used when rendering git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1875499 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/sl/draw/DrawSimpleShape.java | 4 +- .../apache/poi/sl/draw/DrawTextParagraph.java | 4 +- .../apache/poi/xslf/usermodel/XSLFColor.java | 104 ++++++++++-------- .../apache/poi/xslf/usermodel/XSLFShape.java | 23 ++-- 4 files changed, 70 insertions(+), 65 deletions(-) diff --git a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java index cc50ed737c..98e8286be8 100644 --- a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java @@ -139,13 +139,11 @@ public class DrawSimpleShape extends DrawShape { } protected Paint getFillPaint(Graphics2D graphics) { - final PaintStyle ps = getShape().getFillStyle().getPaint(); DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(getShape()); - return drawPaint.getPaint(graphics, ps); + return drawPaint.getPaint(graphics, getShape().getFillStyle().getPaint()); } protected Paint getLinePaint(Graphics2D graphics) { - final PaintStyle ps = getShape().getFillStyle().getPaint(); DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(getShape()); return drawPaint.getPaint(graphics, getShape().getStrokeStyle().getPaint()); } diff --git a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java index c1de9c90e1..c68eb44e0e 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java @@ -568,7 +568,7 @@ public class DrawTextParagraph implements Drawable { text = new StringBuilder(); } - PlaceableShape ps = getParagraphShape(); + final DrawPaint dp = new DrawPaint(getParagraphShape()); DrawFontManager dfm = DrawFactory.getInstance(graphics).getFontManager(graphics); assert(dfm != null); @@ -587,7 +587,7 @@ public class DrawTextParagraph implements Drawable { int endIndex = text.length(); PaintStyle fgPaintStyle = run.getFontColor(); - Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle); + Paint fgPaint = dp.getPaint(graphics, fgPaintStyle); attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex)); Double fontSz = run.getFontSize(); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java index 7a2e6e2b97..4818015b34 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java @@ -19,9 +19,8 @@ package org.apache.poi.xslf.usermodel; import java.awt.Color; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; + +import javax.xml.namespace.QName; import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.usermodel.AbstractColorStyle; @@ -31,6 +30,7 @@ import org.apache.poi.util.Beta; import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference; @@ -42,7 +42,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTScRgbColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTSystemColor; -import org.w3c.dom.Node; /** * Encapsulates logic to read color definitions from DrawingML and convert them to java.awt.Color @@ -50,7 +49,8 @@ import org.w3c.dom.Node; @Beta @Internal public class XSLFColor { - private final static POILogger LOGGER = POILogFactory.getLogger(XSLFColor.class); + private static final POILogger LOGGER = POILogFactory.getLogger(XSLFColor.class); + private static final QName VAL_ATTR = new QName("val"); private XmlObject _xmlObject; private Color _color; @@ -133,37 +133,48 @@ public class XSLFColor { } private Color toColor(XmlObject obj, XSLFTheme theme) { + if (obj == null) { + return _phClr == null ? null : toColor(_phClr, theme); + } + + final XmlCursor cur = obj.newCursor(); Color color = null; - List xo = new ArrayList<>(); - xo.add(obj); - xo.addAll(Arrays.asList(obj.selectPath("*"))); - boolean isFirst = true; - for (XmlObject ch : xo) { - if (ch instanceof CTHslColor) { - color = toColor((CTHslColor)ch); - } else if (ch instanceof CTPresetColor) { - color = toColor((CTPresetColor)ch); - } else if (ch instanceof CTSchemeColor) { - color = toColor((CTSchemeColor)ch, theme); - } else if (ch instanceof CTScRgbColor) { - color = toColor((CTScRgbColor)ch); - } else if (ch instanceof CTSRgbColor) { - color = toColor((CTSRgbColor)ch); - } else if (ch instanceof CTSystemColor) { - color = toColor((CTSystemColor)ch); - } else if (!(ch instanceof CTFontReference)) { - if (!isFirst) { + try { + XmlObject ch; + for (int idx=0; color == null && (ch = nextObject(obj, cur, idx)) != null; idx++) { + if (ch instanceof CTHslColor) { + color = toColor((CTHslColor)ch); + } else if (ch instanceof CTPresetColor) { + color = toColor((CTPresetColor)ch); + } else if (ch instanceof CTSchemeColor) { + color = toColor((CTSchemeColor)ch, theme); + } else if (ch instanceof CTScRgbColor) { + color = toColor((CTScRgbColor)ch); + } else if (ch instanceof CTSRgbColor) { + color = toColor((CTSRgbColor)ch); + } else if (ch instanceof CTSystemColor) { + color = toColor((CTSystemColor)ch); + } else if (!(ch instanceof CTFontReference) && idx > 0) { throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass()); } } - if (color != null) { - break; - } - isFirst = false; + } finally { + cur.dispose(); } return color; } + private static XmlObject nextObject(XmlObject obj, XmlCursor cur, int idx) { + switch (idx) { + case 0: + return obj; + case 1: + return cur.toFirstChild() ? cur.getObject() : null; + default: + return cur.toNextSibling() ? cur.getObject() : null; + } + } + /** * Sets the solid color * @@ -234,29 +245,26 @@ public class XSLFColor { } private static int getRawValue(CTSchemeColor phClr, XmlObject xmlObject, String elem) { - String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem; - - XmlObject[] obj; - - // first ask the context color and if not found, ask the actual color bean - if (phClr != null){ - obj = phClr.selectPath(query); - if (obj.length == 1){ - Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); - if(attr != null) { - return Integer.parseInt(attr.getNodeValue()); + for (XmlObject obj : new XmlObject[]{xmlObject,phClr}) { + if (obj == null) { + continue; + } + XmlCursor cur = obj.newCursor(); + try { + if (!( + cur.toChild(XSLFRelation.NS_DRAWINGML, elem) || + (cur.toFirstChild() && cur.toChild(XSLFRelation.NS_DRAWINGML, elem)) + )) { + continue; } + String str = cur.getAttributeText(VAL_ATTR); + if (str != null && !"".equals(str)) { + return Integer.parseInt(str); + } + } finally { + cur.dispose(); } } - - obj = xmlObject.selectPath(query); - if (obj.length == 1){ - Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val"); - if(attr != null) { - return Integer.parseInt(attr.getNodeValue()); - } - } - return -1; } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index efdbd7b12c..197024064e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -56,6 +56,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; +import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties; import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; @@ -565,25 +566,23 @@ public abstract class XSLFShape implements Shape { return selectPaint(fp.getGradFill(), phClr, theme); } else if (fp.isSetMatrixStyle()) { return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle(), hasPlaceholder); + } else if (phClr != null) { + return selectPaint(phClr, theme); } else { return null; } } + protected PaintStyle selectPaint(CTSchemeColor phClr, final XSLFTheme theme) { + final XSLFColor c = new XSLFColor(null, theme, phClr, _sheet); + return DrawPaint.createSolidPaint(c.getColorStyle()); + } + @SuppressWarnings("WeakerAccess") protected PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) { - if (solidFill.isSetSchemeClr()) { - // if there's a reference to the placeholder color, - // stop evaluating further and let the caller select - // the next style inheritance level -// if (STSchemeColorVal.PH_CLR.equals(solidFill.getSchemeClr().getVal())) { -// return null; -// } - if (phClr == null) { - phClr = solidFill.getSchemeClr(); - } - } - final XSLFColor c = new XSLFColor(solidFill, theme, phClr, _sheet); + CTSchemeColor nestedPhClr = solidFill.getSchemeClr(); + boolean useNested = nestedPhClr != null && nestedPhClr.getVal() != null && !STSchemeColorVal.PH_CLR.equals(nestedPhClr.getVal()); + final XSLFColor c = new XSLFColor(solidFill, theme, useNested ? nestedPhClr : phClr, _sheet); return DrawPaint.createSolidPaint(c.getColorStyle()); }