浏览代码

[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年前
父节点
当前提交
37994bf3e2

+ 85
- 1
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){

+ 68
- 0
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);
}
}

}

+ 37
- 0
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();
}


+ 1
- 0
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()) {

+ 11
- 0
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();

+ 1
- 1
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

正在加载...
取消
保存