Browse Source

[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
tags/REL_5_2_4
PJ Fanning 1 year ago
parent
commit
37994bf3e2

+ 85
- 1
poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java View File

import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.draw.DrawPaint; 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;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.xslf.model.CharacterPropertyFetcher.CharPropFetcher; import org.apache.poi.xslf.model.CharacterPropertyFetcher.CharPropFetcher;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties; import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.xmlbeans.XmlObject; 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.CTFontCollection;
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontScheme; import org.openxmlformats.schemas.drawingml.x2006.main.CTFontScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; 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.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; 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 * Represents a run of text within the containing text body. The run element is the
* lowest level text separation mechanism within a text body. * lowest level text separation mechanism within a text body.
*/ */
@Beta @Beta
public class XSLFTextRun implements TextRun {
public class XSLFTextRun implements TextRun, HighlightColorSupport {
private static final Logger LOG = LogManager.getLogger(XSLFTextRun.class); private static final Logger LOG = LogManager.getLogger(XSLFTextRun.class);


private final XmlObject _r; private final XmlObject _r;
} }




/**
* 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 @Override
public void setFontSize(Double fontSize){ public void setFontSize(Double fontSize){

+ 68
- 0
poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java View File

import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor; import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; 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.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;


import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
import java.util.List; 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.DrawTextFragment;
import org.apache.poi.sl.draw.DrawTextParagraph; import org.apache.poi.sl.draw.DrawTextParagraph;
import org.apache.poi.sl.usermodel.AutoNumberingScheme; import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.xslf.XSLFTestDataSamples; import org.apache.poi.xslf.XSLFTestDataSamples;
import org.apache.poi.xslf.util.DummyGraphics2d;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;


class TestXSLFTextParagraph { class TestXSLFTextParagraph {
assertThrows(IllegalStateException.class, () -> r2.setText("aaa")); 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);
}
}

} }

+ 37
- 0
poi-ooxml/src/test/java/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java View File

import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals; 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.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;


import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;


import org.apache.poi.POIDataSamples; 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.draw.DrawTextParagraph;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.xslf.model.PropertyFetcher;
import org.junit.jupiter.api.Test; 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.CTTextLineBreak;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
r.setSubscript(false); r.setSubscript(false);
assertFalse(r.isSubscript()); 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(); ppt.close();
} }



+ 1
- 0
poi-scratchpad/src/test/java/org/apache/poi/hslf/usermodel/TestTextRun.java View File

} }
} }



@Test @Test
void testAppendEmpty() throws IOException { void testAppendEmpty() throws IOException {
try (HSLFSlideShow ppt = new HSLFSlideShow()) { try (HSLFSlideShow ppt = new HSLFSlideShow()) {

+ 11
- 0
poi/src/main/java/org/apache/poi/sl/draw/DrawTextParagraph.java View File

import org.apache.poi.common.usermodel.fonts.FontGroup.FontGroupRange; import org.apache.poi.common.usermodel.fonts.FontGroup.FontGroupRange;
import org.apache.poi.common.usermodel.fonts.FontInfo; import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.sl.usermodel.AutoNumberingScheme; 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.Hyperlink;
import org.apache.poi.sl.usermodel.Insets2D; import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
import org.apache.poi.util.Units; import org.apache.poi.util.Units;
import org.w3c.dom.Text;


public class DrawTextParagraph implements Drawable { public class DrawTextParagraph implements Drawable {
private static final Logger LOG = LogManager.getLogger(DrawTextParagraph.class); private static final Logger LOG = LogManager.getLogger(DrawTextParagraph.class);


att.put(TextAttribute.FOREGROUND, fgPaint); 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(); Double fontSz = run.getFontSize();
if (fontSz == null) { if (fontSz == null) {
fontSz = paragraph.getDefaultFontSize(); fontSz = paragraph.getDefaultFontSize();

+ 1
- 1
poi/src/main/java/org/apache/poi/sl/usermodel/TextRun.java View File

*/ */
@SuppressWarnings({"unused","java:S1452"}) @SuppressWarnings({"unused","java:S1452"})
public interface TextRun { public interface TextRun {

/** /**
* Type of text capitals * Type of text capitals
*/ */
*/ */
void setFontColor(PaintStyle color); void setFontColor(PaintStyle color);



/** /**
* Returns the font size which is either set directly on this text run or * Returns the font size which is either set directly on this text run or
* given from the slide layout * given from the slide layout

Loading…
Cancel
Save