mirror of
https://github.com/apache/poi.git
synced 2025-03-06 17:09:08 +00:00
[github-409] Textruns not honouring highlight. Thans to gffloodg. This closes #409
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1906248 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1def0cba38
commit
37994bf3e2
@ -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){
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -545,6 +545,7 @@ public final class TestTextRun {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testAppendEmpty() throws IOException {
|
||||
try (HSLFSlideShow ppt = new HSLFSlideShow()) {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user