aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java86
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java68
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java37
-rw-r--r--poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java1
-rw-r--r--poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java11
-rw-r--r--poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java2
6 files changed, 203 insertions, 2 deletions
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
index ea1c179d66..c9f3cfd0c0 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
@@ -30,6 +30,7 @@ import org.apache.poi.ooxml.util.POIXMLUnits;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.draw.DrawPaint;
+import org.apache.poi.sl.usermodel.HighlightColorSupport;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.TextRun;
@@ -40,10 +41,12 @@ import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.apache.poi.xslf.model.CharacterPropertyFetcher.CharPropFetcher;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.xmlbeans.XmlObject;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontCollection;
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
@@ -55,13 +58,14 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
+import org.openxmlformats.schemas.drawingml.x2006.main.impl.CTSRgbColorImpl;
/**
* Represents a run of text within the containing text body. The run element is the
* lowest level text separation mechanism within a text body.
*/
@Beta
-public class XSLFTextRun implements TextRun {
+public class XSLFTextRun implements TextRun, HighlightColorSupport {
private static final Logger LOG = LogManager.getLogger(XSLFTextRun.class);
private final XmlObject _r;
@@ -158,6 +162,86 @@ public class XSLFTextRun implements TextRun {
}
+ /**
+ * Returns the font highlight (background) color for this text run.
+ * This returns a {@link SolidPaint}, or null if no highlight is set.
+ *
+ * @return The font highlight (background) colour associated with the run, null if no highlight.
+ *
+ * @see org.apache.poi.sl.draw.DrawPaint#getPaint(java.awt.Graphics2D, PaintStyle)
+ * @see SolidPaint#getSolidColor()
+ * @since POI 5.2.4
+ */
+ @Override
+ public PaintStyle getHighlightColor() {
+ XSLFShape shape = getParagraph().getParentShape();
+ final boolean hasPlaceholder = shape.getPlaceholder() != null;
+ return fetchCharacterProperty((props, highlightColor) -> fetchHighlightColor(props, highlightColor, shape, hasPlaceholder));
+ }
+
+
+ private static void fetchHighlightColor(CTTextCharacterProperties props, Consumer<PaintStyle> highlightColor, XSLFShape shape, boolean hasPlaceholder) {
+ if (props == null) {
+ return;
+ }
+
+ final CTColor col = props.getHighlight();
+ if (col == null) {
+ return;
+ }
+
+ final CTSRgbColor rgbCol = col.getSrgbClr();
+ final byte[] cols = rgbCol.getVal();
+ final SolidPaint paint = DrawPaint.createSolidPaint(new Color(0xFF & cols[0], 0xFF & cols[1], 0xFF & cols[2]));
+ highlightColor.accept(paint);
+ }
+
+ /**
+ * Sets the font highlight (background) color for this text run - convenience function
+ *
+ * @param color The highlight (background) color to set.
+ * @since POI 5.2.4
+ */
+ @Override
+ public void setHighlightColor(final Color color) {
+ setHighlightColor(DrawPaint.createSolidPaint(color));
+ }
+
+ /**
+ * Set the highlight (background) color for this text run.
+ *
+ * @param color The highlight (background) color to set.
+ * @throws IllegalArgumentException If the supplied paint style is not null or a SolidPaint.
+ *
+ * @see org.apache.poi.sl.draw.DrawPaint#createSolidPaint(Color)
+ * @since POI 5.2.4
+ */
+ @Override
+ public void setHighlightColor(final PaintStyle color) {
+ if (color == null) {
+ final CTTextCharacterProperties rPr = getRPr(true);
+ if (rPr.isSetHighlight()) {
+ rPr.unsetHighlight();
+ }
+ return;
+ }
+
+ if (!(color instanceof SolidPaint)) {
+ throw new IllegalArgumentException("Currently only SolidPaint is supported!");
+ }
+
+ final SolidPaint sp = (SolidPaint)color;
+ final Color c = DrawPaint.applyColorTransform(sp.getSolidColor());
+
+ final CTTextCharacterProperties rPr = getRPr(true);
+ final CTColor highlight = rPr.isSetHighlight() ? rPr.getHighlight() : rPr.addNewHighlight();
+
+ final CTSRgbColor col = CTSRgbColor.Factory.newInstance();
+ col.setVal(new byte[] {(byte)c.getRed(), (byte)c.getGreen(), (byte)c.getBlue()});
+
+ highlight.setSrgbClr(col);
+ }
+
@Override
public void setFontSize(Double fontSize){
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
index d80818d1fe..5d73bdf1a4 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
@@ -19,6 +19,7 @@ package org.apache.poi.xslf.usermodel;
import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -26,16 +27,22 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.awt.Color;
import java.awt.Graphics2D;
+import java.awt.font.TextAttribute;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
import java.util.List;
+import java.util.Map;
+import org.apache.commons.io.output.NullPrintStream;
import org.apache.poi.sl.draw.DrawTextFragment;
import org.apache.poi.sl.draw.DrawTextParagraph;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.xslf.XSLFTestDataSamples;
+import org.apache.poi.xslf.util.DummyGraphics2d;
import org.junit.jupiter.api.Test;
class TestXSLFTextParagraph {
@@ -427,4 +434,65 @@ class TestXSLFTextParagraph {
assertThrows(IllegalStateException.class, () -> r2.setText("aaa"));
}
}
+
+ @Test
+ void testHighlightRender() throws IOException {
+ try (XMLSlideShow ppt = new XMLSlideShow()) {
+ XSLFSlide slide = ppt.createSlide();
+ XSLFTextShape sh = slide.createAutoShape();
+
+ XSLFTextParagraph p = sh.addNewTextParagraph();
+ XSLFTextRun r1 = p.addNewTextRun();
+ r1.setText("This is a ");
+ XSLFTextRun r2 = p.addNewTextRun();
+ r2.setText("highlight");
+ r2.setHighlightColor(Color.yellow);
+ XSLFTextRun r3 = p.addNewTextRun();
+ r3.setText(" test");
+
+ assertEquals("This is a highlight test", sh.getText());
+
+ DummyGraphics2d dgfx = new DummyGraphics2d(new NullPrintStream()) {
+ @Override
+ public void drawString(AttributedCharacterIterator iterator, float x, float y) {
+ // For the test file, common sl draws textruns one by one and not mixed
+ // so we evaluate the whole iterator
+ Map<AttributedCharacterIterator.Attribute, Object> attributes = null;
+ StringBuilder sb = new StringBuilder();
+
+ for (char c = iterator.first();
+ c != CharacterIterator.DONE;
+ c = iterator.next()) {
+ sb.append(c);
+ attributes = iterator.getAttributes();
+ }
+
+ if ("This is a".equals(sb.toString())) {
+ // Should be no background.
+ assertNotNull(attributes);
+ Object background = attributes.get(TextAttribute.BACKGROUND);
+ assertNull(background);
+ }
+ if ("highlight".equals(sb.toString())) {
+ // Should be yellow background.
+ assertNotNull(attributes);
+ Object background = attributes.get(TextAttribute.BACKGROUND);
+ assertNotNull(background);
+ assertTrue(background instanceof Color);
+ assertEquals(Color.yellow, background);
+ }
+ if (" test".equals(sb.toString())) {
+ // Should be no background.
+ assertNotNull(attributes);
+ Object background = attributes.get(TextAttribute.BACKGROUND);
+ assertNull(background);
+ }
+
+ }
+ };
+
+ ppt.getSlides().get(0).draw(dgfx);
+ }
+ }
+
}
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java
index 7e92cea273..944880c121 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java
@@ -23,15 +23,26 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.POIDataSamples;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.draw.DrawTextParagraph;
+import org.apache.poi.sl.usermodel.PaintStyle;
+import org.apache.poi.xslf.model.PropertyFetcher;
import org.junit.jupiter.api.Test;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
@@ -80,6 +91,32 @@ class TestXSLFTextRun {
r.setSubscript(false);
assertFalse(r.isSubscript());
+ // Test highlight get/set.
+ assertNull(r.getHighlightColor());
+ r.setHighlightColor(Color.yellow);
+ assertEquals(DrawPaint.createSolidPaint(Color.yellow), r.getHighlightColor());
+ r.setHighlightColor(DrawPaint.createSolidPaint(Color.blue));
+ assertEquals(DrawPaint.createSolidPaint(Color.blue), r.getHighlightColor());
+
+ r.setHighlightColor((Color) null);
+ assertNull(r.getHighlightColor());
+ r.setHighlightColor((PaintStyle) null);
+ assertNull(r.getHighlightColor());
+
+ try {
+ // make a dummy gradient to test paint rejection.
+ final XSLFSheet sheet = sh.getSheet();
+ final XSLFTheme theme = sheet.getTheme();
+ final CTSchemeColor phClr = CTSchemeColor.Factory.newInstance();
+ final CTGradientFillProperties gradFill = CTGradientFillProperties.Factory.newInstance();
+ final XSLFGradientPaint dummyGrad = new XSLFGradientPaint(gradFill, phClr, theme, sheet);
+
+ r.setHighlightColor(dummyGrad);
+ fail("Expected non solid paint to cause an exception.");
+ } catch (IllegalArgumentException iae) {
+ // Expected, do nothing.
+ }
+
ppt.close();
}
diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java
index f325f2cf92..a361ad650b 100644
--- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java
+++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java
@@ -545,6 +545,7 @@ public final class TestTextRun {
}
}
+
@Test
void testAppendEmpty() throws IOException {
try (HSLFSlideShow ppt = new HSLFSlideShow()) {
diff --git a/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java b/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java
index b0cd9598de..a07b15efce 100644
--- a/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java
+++ b/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java
@@ -47,6 +47,7 @@ import org.apache.poi.common.usermodel.fonts.FontGroup;
import org.apache.poi.common.usermodel.fonts.FontGroup.FontGroupRange;
import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
+import org.apache.poi.sl.usermodel.HighlightColorSupport;
import org.apache.poi.sl.usermodel.Hyperlink;
import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.PaintStyle;
@@ -65,6 +66,7 @@ import org.apache.poi.util.Internal;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.Units;
+import org.w3c.dom.Text;
public class DrawTextParagraph implements Drawable {
private static final Logger LOG = LogManager.getLogger(DrawTextParagraph.class);
@@ -610,6 +612,15 @@ public class DrawTextParagraph implements Drawable {
att.put(TextAttribute.FOREGROUND, fgPaint);
+ if (run instanceof HighlightColorSupport) {
+ // Highlight color is only supported in XSLF (PPTX) text runs.
+ final PaintStyle highlightPaintStyle = ((HighlightColorSupport)run).getHighlightColor();
+ if (highlightPaintStyle != null) {
+ final Paint bgPaint = dp.getPaint(graphics, highlightPaintStyle);
+ att.put(TextAttribute.BACKGROUND, bgPaint);
+ }
+ }
+
Double fontSz = run.getFontSize();
if (fontSz == null) {
fontSz = paragraph.getDefaultFontSize();
diff --git a/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java b/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java
index 11bc79c8ec..85a7679c30 100644
--- a/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java
+++ b/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java
@@ -29,6 +29,7 @@ import org.apache.poi.util.Internal;
*/
@SuppressWarnings({"unused","java:S1452"})
public interface TextRun {
+
/**
* Type of text capitals
*/
@@ -78,7 +79,6 @@ public interface TextRun {
*/
void setFontColor(PaintStyle color);
-
/**
* Returns the font size which is either set directly on this text run or
* given from the slide layout