From 9b886f3091bdcd2804b46616d634f2a72588887d Mon Sep 17 00:00:00 2001 From: artragis Date: Mon, 4 Jan 2021 19:16:00 +0100 Subject: [PATCH] poi-ooxml: add new API to add text transparency on XLSX This API uses XSSFColor built with alpha channel to set up the right value. We must take care of the fact Excel uses 1000th of percent and positive numbers --- .../poi/xssf/usermodel/XSSFTextParagraph.java | 36 ++++++ .../xssf/usermodel/TestXSSFTextParagraph.java | 103 ++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java index 0d33e0c4f66..69fdb2f082e 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java @@ -28,6 +28,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more import org.apache.poi.xssf.model.ParagraphPropertyFetcher; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.drawingml.x2006.main.impl.STPositiveFixedPercentageImpl; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; /** @@ -863,6 +864,41 @@ private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){ return ok; } + public void setTextFillColor(XSSFColor color) { + if (getTextRuns().isEmpty()) { + addNewTextRun(); + } + XSSFTextRun run = getTextRuns().get(getTextRuns().size() - 1); + if (!run.getRPr().isSetSolidFill()) { + run.getRPr().addNewSolidFill(); + } else if (run.getRPr().getSolidFill().isSetSrgbClr()){ + run.getRPr().getSolidFill().unsetSrgbClr(); + } else if (run.getRPr().getSolidFill().isSetScrgbClr()){ + run.getRPr().getSolidFill().unsetScrgbClr(); + } else if (run.getRPr().getSolidFill().isSetSchemeClr()){ + run.getRPr().getSolidFill().unsetSchemeClr(); + } else if (run.getRPr().getSolidFill().isSetSysClr()){ + run.getRPr().getSolidFill().unsetSysClr(); + } else if (run.getRPr().getSolidFill().isSetHslClr()){ + run.getRPr().getSolidFill().unsetHslClr(); + } else if (run.getRPr().getSolidFill().isSetPrstClr()){ + run.getRPr().getSolidFill().unsetPrstClr(); + } + CTSRgbColor srgbClr = run.getRPr().getSolidFill().addNewSrgbClr(); + srgbClr.setVal(color.getRGB()); + byte[] argbArray = color.getARGB(); + if (argbArray[0] != -1) { + int unsignedTransparency; + if (argbArray[0] >= 0) { + unsignedTransparency = argbArray[0]; + } else { + unsignedTransparency = 255 & argbArray[0]; + } + int alphaInTenthOfPercent = 100_000 * unsignedTransparency / 255; + srgbClr.addNewAlpha().setVal(alphaInTenthOfPercent); + } + } + @Override public String toString(){ return "[" + getClass() + "]" + getText(); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTextParagraph.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTextParagraph.java index bfd4814419c..750841e13a7 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTextParagraph.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTextParagraph.java @@ -19,10 +19,12 @@ Licensed to the Apache Software Foundation (ASF) under one or more import static org.junit.jupiter.api.Assertions.*; import java.awt.Color; +import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import org.junit.jupiter.api.Test; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; public class TestXSSFTextParagraph { @Test @@ -192,4 +194,105 @@ public void testXSSFTextParagraph() throws IOException { new XSSFTextParagraph(text.getXmlObject(), shape.getCTShape()); } } + @Test + public void testXSSFTextParagraphWithAlpha() throws IOException { + try (XSSFWorkbook wb = new XSSFWorkbook()) { + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); + XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4)); + XSSFRichTextString rt = new XSSFRichTextString("Test String"); + + XSSFFont font = wb.createFont(); + Color color = new Color(0, 255, 255, 10); + XSSFColor textColor = new XSSFColor(color, wb.getStylesSource().getIndexedColors()); + textColor.setARGBHex("0A00FFFF"); + font.setColor(textColor); + font.setFontName("Arial"); + rt.applyFont(font); + shape.setText(rt); + + List paras = shape.getTextParagraphs(); + assertEquals(1, paras.size()); + paras.get(0).setTextFillColor(textColor); + XSSFTextParagraph testedParagraph = paras.get(0); + CTSolidColorFillProperties properties = testedParagraph.getTextRuns() + .get(testedParagraph.getTextRuns().size() - 1) + .getRPr() + .getSolidFill(); + assertNotNull(properties); + assertNotNull(properties.getSrgbClr()); + assertEquals(textColor.getRGB()[0], properties.getSrgbClr().getVal()[0]); + assertEquals(textColor.getRGB()[1], properties.getSrgbClr().getVal()[1]); + assertEquals(textColor.getRGB()[2], properties.getSrgbClr().getVal()[2]); + // 10 is 3.921% of transparency therefore 3912 1000th% of transparency + assertEquals(3921, properties.getSrgbClr().getAlphaArray()[0].getVal()); + } + } + @Test + public void testXSSFTextParagraphWithoutAlpha() throws IOException { + try (XSSFWorkbook wb = new XSSFWorkbook()) { + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); + XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4)); + XSSFRichTextString rt = new XSSFRichTextString("Test String"); + + XSSFFont font = wb.createFont(); + Color color = new Color(0, 255, 255, 10); + XSSFColor textColor = new XSSFColor(color, wb.getStylesSource().getIndexedColors()); + font.setColor(textColor); + font.setFontName("Arial"); + rt.applyFont(font); + shape.setText(rt); + + List paras = shape.getTextParagraphs(); + assertEquals(1, paras.size()); + paras.get(0).setTextFillColor(textColor); + XSSFTextParagraph testedParagraph = paras.get(0); + CTSolidColorFillProperties properties = testedParagraph.getTextRuns() + .get(testedParagraph.getTextRuns().size() - 1) + .getRPr() + .getSolidFill(); + assertNotNull(properties); + assertNotNull(properties.getSrgbClr()); + assertEquals(textColor.getRGB()[0], properties.getSrgbClr().getVal()[0]); + assertEquals(textColor.getRGB()[1], properties.getSrgbClr().getVal()[1]); + assertEquals(textColor.getRGB()[2], properties.getSrgbClr().getVal()[2]); + // 10 is 3.921% of transparency therefore 3912 1000th% of transparency + assertEquals(0, properties.getSrgbClr().getAlphaArray().length); + } + } + @Test + public void testXSSFTextParagraphNegativeByteAlpha() throws IOException { + try (XSSFWorkbook wb = new XSSFWorkbook()) { + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); + XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4)); + XSSFRichTextString rt = new XSSFRichTextString("Test String"); + + XSSFFont font = wb.createFont(); + Color color = new Color(0, 255, 255, 10); + XSSFColor textColor = new XSSFColor(color, wb.getStylesSource().getIndexedColors()); + textColor.setARGBHex("FA00FFFF"); + //font.setColor(textColor); + font.setFontName("Arial"); + rt.applyFont(font); + shape.setText(rt); + + List paras = shape.getTextParagraphs(); + assertEquals(1, paras.size()); + paras.get(0).setTextFillColor(textColor); + XSSFTextParagraph testedParagraph = paras.get(0); + CTSolidColorFillProperties properties = testedParagraph.getTextRuns() + .get(testedParagraph.getTextRuns().size() - 1) + .getRPr() + .getSolidFill(); + assertNotNull(properties); + assertNotNull(properties.getSrgbClr()); + assertEquals(textColor.getRGB()[0], properties.getSrgbClr().getVal()[0]); + assertEquals(textColor.getRGB()[1], properties.getSrgbClr().getVal()[1]); + assertEquals(textColor.getRGB()[2], properties.getSrgbClr().getVal()[2]); + // 250 is 3.921% of transparency therefore 3912 1000th% of transparency + assertEquals(98039, properties.getSrgbClr().getAlphaArray()[0].getVal()); + } + } }