From fd3df13143962a28d23bac1fb34fbbbde5f3d97c Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Sun, 22 May 2016 23:58:07 +0000 Subject: [PATCH] #58217 - XSLF: support alpha channel on solid colors (fill, line, text) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1745101 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/sl/usermodel/PresetColor.java | 62 ++++++++-------- .../apache/poi/xslf/usermodel/XSLFColor.java | 71 +++++++++++++++++-- .../poi/xslf/usermodel/XSLFSimpleShape.java | 68 +++++++++--------- .../poi/xslf/usermodel/XSLFTextRun.java | 14 ++-- .../org/apache/poi/xslf/TestXSLFBugs.java | 29 +++++++- .../poi/xslf/usermodel/TestXSLFColor.java | 15 ++-- 6 files changed, 175 insertions(+), 84 deletions(-) diff --git a/src/java/org/apache/poi/sl/usermodel/PresetColor.java b/src/java/org/apache/poi/sl/usermodel/PresetColor.java index 0860e7dd12..72e9fc661f 100644 --- a/src/java/org/apache/poi/sl/usermodel/PresetColor.java +++ b/src/java/org/apache/poi/sl/usermodel/PresetColor.java @@ -36,58 +36,60 @@ public enum PresetColor { // default colors for theme-depending colors taken from ... (last post): // https://social.technet.microsoft.com/Forums/windows/en-US/ac76cc56-6ff2-4778-b260-8141d7170a3b/windows-7-highlight-text-color-or-selected-text-color-in-aero + // see ST_SystemColorVal for system color names + /** The system-defined color of the active window's border. */ - ActiveBorder (0xffb4b4b4, 1, null), + ActiveBorder (0xffb4b4b4, 1, "activeBorder"), /** The system-defined color of the background of the active window's title bar. */ - ActiveCaption (0xff99b4d1, 2, null), + ActiveCaption (0xff99b4d1, 2, "activeCaption"), /** The system-defined color of the text in the active window's title bar. */ - ActiveCaptionText (0xff000000, 3, null), + ActiveCaptionText (0xff000000, 3, "captionText"), /** The application workspace is the area in a multiple-document view that is not being occupied by documents. */ - AppWorkspace (0xffababab, 4, null), + AppWorkspace (0xffababab, 4, "appWorkspace"), /** The system-defined face color of a 3-D element. */ - Control (0xfff0f0f0, 5, null), + Control (0xfff0f0f0, 5, "btnFace"), /** The system-defined shadow color of a 3-D element. The shadow color is applied to parts of a 3-D element that face away from the light source. */ - ControlDark (0xff696969, 6, null), + ControlDark (0xff696969, 6, "btnShadow"), /** The system-defined color that is the dark shadow color of a 3-D element. The dark shadow color is applied to the parts of a 3-D element that are the darkest color. */ - ControlDarkDark (0xff000000, 7, null), + ControlDarkDark (0xff000000, 7, "3dDkShadow"), /** The system-defined color that is the light color of a 3-D element. The light color is applied to parts of a 3-D element that face the light source. */ - ControlLight (0xffe3e3e3, 8, null), + ControlLight (0xffe3e3e3, 8, "btnHighlight"), /** The system-defined highlight color of a 3-D element. The highlight color is applied to the parts of a 3-D element that are the lightest color. */ - ControlLightLight (0xffe3e3e3, 9, null), + ControlLightLight (0xffe3e3e3, 9, "3dLight"), /** The system-defined color of text in a 3-D element. */ - ControlText (0xff000000, 10, null), + ControlText (0xff000000, 10, "btnText"), /** The system-defined color of the desktop. */ - Desktop (0xff000000, 11, null), + Desktop (0xff000000, 11, "background"), /** The system-defined color of dimmed text. Items in a list that are disabled are displayed in dimmed text. */ - GrayText (0xff6d6d6d, 12, null), + GrayText (0xff6d6d6d, 12, "grayText"), /** The system-defined color of the background of selected items. This includes selected menu items as well as selected text. */ - Highlight (0xff3399ff, 13, null), + Highlight (0xff3399ff, 13, "highlight"), /** The system-defined color of the text of selected items. */ - HighlightText (0xffffffff, 14, null), + HighlightText (0xffffffff, 14, "highlightText"), /** The system-defined color used to designate a hot-tracked item. Single-clicking a hot-tracked item executes the item. */ - HotTrack (0xff0066cc, 15, null), + HotTrack (0xff0066cc, 15, "hotLight"), /** The system-defined color of an inactive window's border. */ - InactiveBorder (0xfff4f7fc, 16, null), + InactiveBorder (0xfff4f7fc, 16, "inactiveBorder"), /** The system-defined color of the background of an inactive window's title bar. */ - InactiveCaption (0xffbfcddb, 17, null), + InactiveCaption (0xffbfcddb, 17, "inactiveCaption"), /** The system-defined color of the text in an inactive window's title bar. */ - InactiveCaptionText (0xff000000, 18, null), + InactiveCaptionText (0xff000000, 18, "inactiveCaptionText"), /** The system-defined color of the background of a ToolTip. */ - Info (0xffffffe1, 19, null), + Info (0xffffffe1, 19, "infoBk"), /** The system-defined color of the text of a ToolTip. */ - InfoText (0xff000000, 20, null), + InfoText (0xff000000, 20, "infoText"), /** The system-defined color of a menu's background. */ - Menu (0xfff0f0f0, 21, null), + Menu (0xfff0f0f0, 21, "menu"), /** The system-defined color of a menu's text. */ - MenuText (0xff000000, 22, null), + MenuText (0xff000000, 22, "menuText"), /** The system-defined color of the background of a scroll bar. */ - ScrollBar (0xffc8c8c8, 23, null), + ScrollBar (0xffc8c8c8, 23, "scrollBar"), /** The system-defined color of the background in the client area of a window. */ - Window (0xffffffff, 24, null), + Window (0xffffffff, 24, "window"), /** The system-defined color of a window frame. */ - WindowFrame (0xff646464, 25, null), + WindowFrame (0xff646464, 25, "windowFrame"), /** The system-defined color of the text in the client area of a window. */ - WindowText (0xff000000, 26, null), + WindowText (0xff000000, 26, "windowText"), Transparent (0x00ffffff, 27, null), AliceBlue (0xfff0f8ff, 28, "aliceBlue"), AntiqueWhite (0xfffaebd7, 29, "antiqueWhite"), @@ -236,13 +238,13 @@ public enum PresetColor { /** The system-defined color that is the shadow color of a 3-D element. This color is applied to parts of a 3-D element that face away from the light source. */ ButtonShadow (0xffa0a0a0, 170, null), /** The system-defined color of the lightest color in the color gradient of an active window's title bar. */ - GradientActiveCaption (0xffb9d1ea, 171, null), + GradientActiveCaption (0xffb9d1ea, 171, "gradientActiveCaption"), /** The system-defined color of the lightest color in the color gradient of an inactive window's title bar. */ - GradientInactiveCaption (0xffd7e4f2, 172, null), + GradientInactiveCaption (0xffd7e4f2, 172, "gradientInactiveCaption"), /** The system-defined color of the background of a menu bar. */ - MenuBar (0xfff0f0f0, 173, null), + MenuBar (0xfff0f0f0, 173, "menuBar"), /** The system-defined color used to highlight menu items when the menu appears as a flat menu. */ - MenuHighlight (0xff3399ff, 174, null) + MenuHighlight (0xff3399ff, 174, "menuHighlight") ; public Color color; 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 f30fb5efd2..f2e94faeaf 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java @@ -25,6 +25,8 @@ import org.apache.poi.sl.usermodel.ColorStyle; import org.apache.poi.sl.usermodel.PresetColor; 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.XmlObject; import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor; @@ -32,17 +34,18 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; 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 - * - * @author Yegor Kozlov */ @Beta @Internal public class XSLFColor { + private static POILogger LOGGER = POILogFactory.getLogger(XSLFColor.class); + private XmlObject _xmlObject; private Color _color; private CTSchemeColor _phClr; @@ -156,10 +159,14 @@ public class XSLFColor { byte[] val = sys.getLastClr(); color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); } else { - // YK: color is a string like "menuText" or "windowText", we return black for such cases - @SuppressWarnings("unused") String colorName = sys.getVal().toString(); - color = Color.black; + PresetColor pc = PresetColor.valueOfOoxmlId(colorName); + if (pc != null) { + color = pc.color; + } + if (color == null) { + color = Color.black; + } } } else { throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass()); @@ -168,6 +175,60 @@ public class XSLFColor { return color; } + /** + * Sets the solid color + * + * @param color solid color + */ + @Internal + protected void setColor(Color color) { + if (!(_xmlObject instanceof CTSolidColorFillProperties)) { + LOGGER.log(POILogger.ERROR, "XSLFColor.setColor currently only supports CTSolidColorFillProperties"); + return; + } + CTSolidColorFillProperties fill = (CTSolidColorFillProperties)_xmlObject; + if (fill.isSetSrgbClr()) { + fill.unsetSrgbClr(); + } + + CTSRgbColor rgb = fill.addNewSrgbClr(); + + float[] rgbaf = color.getRGBComponents(null); + int r = color.getRed(), g = color.getGreen(), b = color.getBlue(); + if (rgbaf[0]*255f == r && rgbaf[1]*255f == g && rgbaf[2]*255f == b) { + rgb.setVal(new byte[]{(byte)r, (byte)g, (byte)b }); + } else { + rgb.addNewRed().setVal((int)(100000 * rgbaf[0])); + rgb.addNewGreen().setVal((int)(100000 * rgbaf[1])); + rgb.addNewBlue().setVal((int)(100000 * rgbaf[2])); + } + + // alpha (%) + if (rgbaf.length == 4 && rgbaf[3] < 1f) { + rgb.addNewAlpha().setVal((int)(100000 * rgbaf[3])); + } + + if (fill.isSetHslClr()) { + fill.unsetHslClr(); + } + + if (fill.isSetPrstClr()) { + fill.unsetPrstClr(); + } + + if (fill.isSetSchemeClr()) { + fill.unsetSchemeClr(); + } + + if (fill.isSetScrgbClr()) { + fill.unsetScrgbClr(); + } + + if (fill.isSetSysClr()) { + fill.unsetSysClr(); + } + } + private int getRawValue(String elem) { String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index 636647ef2e..1f3393d1f0 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -59,7 +59,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; @@ -218,25 +217,31 @@ public abstract class XSLFSimpleShape extends XSLFShape */ public void setLineColor(Color color) { CTShapeProperties spPr = getSpPr(); + CTLineProperties ln = spPr.getLn(); if (color == null) { - if (spPr.isSetLn() && spPr.getLn().isSetSolidFill()) - spPr.getLn().unsetSolidFill(); + if (ln == null) { + return; + } + + if (ln.isSetSolidFill()) { + ln.unsetSolidFill(); + } + + if (!ln.isSetNoFill()) { + ln.addNewNoFill(); + } } else { - CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr - .addNewLn(); - - CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); - rgb.setVal(new byte[]{(byte) color.getRed(), - (byte) color.getGreen(), (byte) color.getBlue()}); + if (ln == null) { + ln = spPr.addNewLn(); + } + if (ln.isSetNoFill()) { + ln.unsetNoFill(); + } + + CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill(); - CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln - .getSolidFill() : ln.addNewSolidFill(); - fill.setSrgbClr(rgb); - if(fill.isSetHslClr()) fill.unsetHslClr(); - if(fill.isSetPrstClr()) fill.unsetPrstClr(); - if(fill.isSetSchemeClr()) fill.unsetSchemeClr(); - if(fill.isSetScrgbClr()) fill.unsetScrgbClr(); - if(fill.isSetSysClr()) fill.unsetSysClr(); + XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); + col.setColor(color); } } @@ -548,25 +553,22 @@ public abstract class XSLFSimpleShape extends XSLFShape public void setFillColor(Color color) { CTShapeProperties spPr = getSpPr(); if (color == null) { - if (spPr.isSetSolidFill()) spPr.unsetSolidFill(); + if (spPr.isSetSolidFill()) { + spPr.unsetSolidFill(); + } - if (!spPr.isSetNoFill()) spPr.addNewNoFill(); + if (!spPr.isSetNoFill()) { + spPr.addNewNoFill(); + } } else { - if (spPr.isSetNoFill()) spPr.unsetNoFill(); - - CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr - .getSolidFill() : spPr.addNewSolidFill(); - - CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); - rgb.setVal(new byte[]{(byte) color.getRed(), - (byte) color.getGreen(), (byte) color.getBlue()}); + if (spPr.isSetNoFill()) { + spPr.unsetNoFill(); + } - fill.setSrgbClr(rgb); - if(fill.isSetHslClr()) fill.unsetHslClr(); - if(fill.isSetPrstClr()) fill.unsetPrstClr(); - if(fill.isSetSchemeClr()) fill.unsetSchemeClr(); - if(fill.isSetScrgbClr()) fill.unsetScrgbClr(); - if(fill.isSetSysClr()) fill.unsetSysClr(); + CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill(); + + XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr()); + col.setColor(color); } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java index 08804b0a8e..1a6bcc384a 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java @@ -96,19 +96,13 @@ public class XSLFTextRun implements TextRun { throw new IllegalArgumentException("Currently only SolidPaint is supported!"); } SolidPaint sp = (SolidPaint)color; + Color c = DrawPaint.applyColorTransform(sp.getSolidColor()); CTTextCharacterProperties rPr = getRPr(); CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill(); - CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr(); - Color c = DrawPaint.applyColorTransform(sp.getSolidColor()); - clr.setVal(new byte[]{(byte)c.getRed(), (byte)c.getGreen(), (byte)c.getBlue()}); - - if(fill.isSetHslClr()) fill.unsetHslClr(); - if(fill.isSetPrstClr()) fill.unsetPrstClr(); - if(fill.isSetSchemeClr()) fill.unsetSchemeClr(); - if(fill.isSetScrgbClr()) fill.unsetScrgbClr(); - if(fill.isSetSysClr()) fill.unsetSysClr(); - + + XSLFColor col = new XSLFColor(fill, getParentParagraph().getParentShape().getSheet().getTheme(), fill.getSchemeClr()); + col.setColor(c); } @Override diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java index 4b43370df6..7c55ce7fb7 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java @@ -16,9 +16,9 @@ ==================================================================== */ package org.apache.poi.xslf; -import static junit.framework.TestCase.assertEquals; import static org.apache.poi.POITestCase.assertContains; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -40,11 +40,14 @@ import javax.imageio.ImageIO; import org.apache.poi.POIDataSamples; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLDocumentPart.RelationPart; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.PictureData.PictureType; +import org.apache.poi.sl.usermodel.ShapeType; import org.apache.poi.xslf.usermodel.DrawingParagraph; import org.apache.poi.xslf.usermodel.DrawingTextBody; import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.poi.xslf.usermodel.XSLFAutoShape; import org.apache.poi.xslf.usermodel.XSLFHyperlink; import org.apache.poi.xslf.usermodel.XSLFPictureData; import org.apache.poi.xslf.usermodel.XSLFPictureShape; @@ -472,4 +475,28 @@ public class TestXSLFBugs { ppt2.close(); } + + @Test + public void bug58217() throws IOException { + XMLSlideShow ppt1 = new XMLSlideShow(); + XSLFSlide sl = ppt1.createSlide(); + XSLFAutoShape as = sl.createAutoShape(); + as.setShapeType(ShapeType.STAR_10); + as.setAnchor(new Rectangle2D.Double(100,100,300,300)); + as.setFillColor(new Color(1f,1f,0f,0.1f)); + as.setLineColor(new Color(1f,1f,0f,0.4f)); + as.setText("Alpha"); + as.getTextParagraphs().get(0).getTextRuns().get(0).setFontColor(new Color(1f,1f,0f,0.6f)); + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt1.close(); + sl = ppt2.getSlides().get(0); + as = (XSLFAutoShape)sl.getShapes().get(0); + SolidPaint ps = (SolidPaint)as.getFillStyle().getPaint(); + assertEquals(10000, ps.getSolidColor().getAlpha()); + ps = (SolidPaint)as.getStrokeStyle().getPaint(); + assertEquals(40000, ps.getSolidColor().getAlpha()); + ps = (SolidPaint)as.getTextParagraphs().get(0).getTextRuns().get(0).getFontColor(); + assertEquals(60000, ps.getSolidColor().getAlpha()); + ppt2.close(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java index d789157789..8a923c29d6 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java @@ -17,7 +17,7 @@ package org.apache.poi.xslf.usermodel; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.awt.Color; import java.io.IOException; @@ -154,9 +154,14 @@ public class TestXSLFColor { for(PresetColor pc : PresetColor.values()) { if (pc.ooxmlId == null) continue; xml = CTColor.Factory.newInstance(); - STPresetColorVal.Enum val = STPresetColorVal.Enum.forString(pc.ooxmlId); - assertNotNull(pc.ooxmlId, val); - xml.addNewPrstClr().setVal(val); + STPresetColorVal.Enum preVal = STPresetColorVal.Enum.forString(pc.ooxmlId); + STSystemColorVal.Enum sysVal = STSystemColorVal.Enum.forString(pc.ooxmlId); + assertTrue(pc.ooxmlId, preVal != null || sysVal != null); + if (preVal != null) { + xml.addNewPrstClr().setVal(preVal); + } else { + xml.addNewSysClr().setVal(sysVal); + } color = new XSLFColor(xml, null, null); assertEquals(pc.color, color.getColor()); } @@ -166,7 +171,7 @@ public class TestXSLFColor { public void testSys() { CTColor xml = CTColor.Factory.newInstance(); CTSystemColor sys = xml.addNewSysClr(); - sys.setVal(STSystemColorVal.GRAY_TEXT); + sys.setVal(STSystemColorVal.CAPTION_TEXT); XSLFColor color = new XSLFColor(xml, null, null); assertEquals(Color.black, color.getColor()); -- 2.39.5