You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2022/12/28 17:45:21 UTC

svn commit: r1906248 - in /poi/trunk: poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/ poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/ poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/ poi/src/main/java/org/apache/poi/sl/draw/ po...

Author: fanningpj
Date: Wed Dec 28 17:45:21 2022
New Revision: 1906248

URL: http://svn.apache.org/viewvc?rev=1906248&view=rev
Log:
[github-409] Textruns not honouring highlight. Thans to gffloodg. This closes #409

Modified:
    poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
    poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
    poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java
    poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java
    poi/trunk/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java
    poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java

Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java?rev=1906248&r1=1906247&r2=1906248&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java (original)
+++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java Wed Dec 28 17:45:21 2022
@@ -30,6 +30,7 @@ import org.apache.poi.ooxml.util.POIXMLU
 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.Charact
 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.drawin
 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 Text
     }
 
 
+    /**
+     * 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){

Modified: poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java?rev=1906248&r1=1906247&r2=1906248&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java (original)
+++ poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java Wed Dec 28 17:45:21 2022
@@ -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.Assu
 
 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);
+        }
+    }
+
 }

Modified: poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java?rev=1906248&r1=1906247&r2=1906248&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java (original)
+++ poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java Wed Dec 28 17:45:21 2022
@@ -23,15 +23,26 @@ import static org.junit.jupiter.api.Asse
 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();
     }
 

Modified: poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java?rev=1906248&r1=1906247&r2=1906248&view=diff
==============================================================================
--- poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java (original)
+++ poi/trunk/poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java Wed Dec 28 17:45:21 2022
@@ -545,6 +545,7 @@ public final class TestTextRun {
         }
     }
 
+
     @Test
     void testAppendEmpty() throws IOException {
         try (HSLFSlideShow ppt = new HSLFSlideShow()) {

Modified: poi/trunk/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java?rev=1906248&r1=1906247&r2=1906248&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java Wed Dec 28 17:45:21 2022
@@ -47,6 +47,7 @@ import org.apache.poi.common.usermodel.f
 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 implement
 
             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();

Modified: poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java?rev=1906248&r1=1906247&r2=1906248&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java Wed Dec 28 17:45:21 2022
@@ -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



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org