diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2020-06-04 23:17:44 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2020-06-04 23:17:44 +0000 |
commit | 5a18307eb051603509c8b8147f4dfdf0e8fe56b2 (patch) | |
tree | 70a5e2c1ff908c4a98a614b92f5992c8c2891060 /src/ooxml/java/org | |
parent | 84330c6aa3a96fff4bbd5593b7173209187ec474 (diff) | |
download | poi-5a18307eb051603509c8b8147f4dfdf0e8fe56b2.tar.gz poi-5a18307eb051603509c8b8147f4dfdf0e8fe56b2.zip |
63290 - PPTX To Png changes font sizes and colors
various fixes to HSLF
moved line spacing to the following line
refactored PropertyFetcher with lambdas
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1878492 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/ooxml/java/org')
7 files changed, 409 insertions, 464 deletions
diff --git a/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java index fd8b40fc09..beb8c5a431 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java @@ -19,22 +19,94 @@ package org.apache.poi.xslf.model; +import static org.apache.poi.xslf.model.ParagraphPropertyFetcher.getThemeProps; +import static org.apache.poi.xslf.model.ParagraphPropertyFetcher.select; + +import java.util.function.Consumer; + +import org.apache.poi.util.Internal; +import org.apache.poi.xslf.usermodel.XSLFShape; +import org.apache.poi.xslf.usermodel.XSLFSheet; +import org.apache.poi.xslf.usermodel.XSLFSlideMaster; +import org.apache.poi.xslf.usermodel.XSLFTextRun; +import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; -public abstract class CharacterPropertyFetcher<T> extends ParagraphPropertyFetcher<T> { - public CharacterPropertyFetcher(int level) { - super(level); +@Internal +public final class CharacterPropertyFetcher<T> extends PropertyFetcher<T> { + public interface CharPropFetcher<S> { + void fetch (CTTextCharacterProperties props, Consumer<S> val); + } + + private final XSLFTextRun run; + int _level; + private final CharPropFetcher<T> fetcher; + + public CharacterPropertyFetcher(XSLFTextRun run, CharPropFetcher<T> fetcher) { + _level = run.getParagraph().getIndentLevel(); + this.fetcher = fetcher; + this.run = run; + } + + public boolean fetch(XSLFShape shape) { + // this is only called when propagating to parent styles + try { + fetchProp(select(shape, _level)); + } catch (XmlException ignored) { + } + return isSet(); } - public boolean fetch(CTTextParagraphProperties props) { - if (props != null && props.isSetDefRPr()) { - return fetch(props.getDefRPr()); + + public T fetchProperty(XSLFShape shape) { + final XSLFSheet sheet = shape.getSheet(); + + + if (!(sheet instanceof XSLFSlideMaster)) { + fetchRunProp(); + fetchShapeProp(shape); + fetchThemeProp(shape); } - return false; + fetchMasterProp(); + + return isSet() ? getValue() : null; } - public abstract boolean fetch(CTTextCharacterProperties props); + private void fetchRunProp() { + fetchProp(run.getRPr(false)); + } + private void fetchShapeProp(XSLFShape shape) { + if (!isSet()) { + shape.fetchShapeProperty(this); + } + } + + private void fetchThemeProp(XSLFShape shape) { + if (!isSet()) { + fetchProp(getThemeProps(shape, _level)); + } + } + + private void fetchMasterProp() { + // defaults for placeholders are defined in the slide master + // TODO: determine master shape + if (!isSet()) { + fetchProp(run.getParagraph().getDefaultMasterStyle()); + } + } + + private void fetchProp(CTTextParagraphProperties props) { + if (props != null) { + fetchProp(props.getDefRPr()); + } + } + + private void fetchProp(CTTextCharacterProperties props) { + if (props != null) { + fetcher.fetch(props, this::setValue); + } + } }
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java index 1d2c3422c8..9a722c59f6 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/ParagraphPropertyFetcher.java @@ -19,43 +19,144 @@ package org.apache.poi.xslf.model; +import java.util.function.Consumer; + import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamReader; +import org.apache.poi.util.Internal; +import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFShape; +import org.apache.poi.xslf.usermodel.XSLFSheet; +import org.apache.poi.xslf.usermodel.XSLFSlideMaster; +import org.apache.poi.xslf.usermodel.XSLFTextParagraph; import org.apache.xmlbeans.XmlException; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; -public abstract class ParagraphPropertyFetcher<T> extends PropertyFetcher<T> { +@Internal +public final class ParagraphPropertyFetcher<T> extends PropertyFetcher<T> { + public interface ParaPropFetcher<S> { + void fetch (CTTextParagraphProperties props, Consumer<S> val); + } + + static final String PML_NS = "http://schemas.openxmlformats.org/presentationml/2006/main"; static final String DML_NS = "http://schemas.openxmlformats.org/drawingml/2006/main"; private static final QName[] TX_BODY = { new QName(PML_NS, "txBody") }; private static final QName[] LST_STYLE = { new QName(DML_NS, "lstStyle") }; + private final XSLFTextParagraph para; int _level; + private final ParaPropFetcher<T> fetcher; - public ParagraphPropertyFetcher(int level) { - _level = level; + public ParagraphPropertyFetcher(XSLFTextParagraph para, ParaPropFetcher<T> fetcher) { + this.para = para; + _level = para.getIndentLevel(); + this.fetcher = fetcher; } public boolean fetch(XSLFShape shape) { - QName[] lvlProp = { new QName(DML_NS, "lvl" + (_level + 1) + "pPr") }; - CTTextParagraphProperties props = null; + // this is only called when propagating to parent styles try { - props = shape.selectProperty( - CTTextParagraphProperties.class, ParagraphPropertyFetcher::parse, TX_BODY, LST_STYLE, lvlProp); - return (props != null) && fetch(props); - } catch (XmlException e) { - return false; + fetchProp(select(shape, _level)); + } catch (XmlException ignored) { } + return isSet(); } - private static CTTextParagraphProperties parse(XMLStreamReader reader) throws XmlException { + public T fetchProperty(XSLFShape shape) { + final XSLFSheet sheet = shape.getSheet(); + + if (!(sheet instanceof XSLFSlideMaster)) { + fetchParagraphProp(); + fetchShapeProp(shape); + fetchThemeProp(shape); + } + + fetchMasterProp(); + + return isSet() ? getValue() : null; + } + + private void fetchParagraphProp() { + fetchProp(para.getXmlObject().getPPr()); + } + + private void fetchShapeProp(XSLFShape shape) { + if (!isSet()) { + shape.fetchShapeProperty(this); + } + } + + private void fetchThemeProp(XSLFShape shape) { + if (!isSet()) { + fetchProp(getThemeProps(shape, _level)); + } + } + + private void fetchMasterProp() { + // defaults for placeholders are defined in the slide master + // TODO: determine master shape + if (!isSet()) { + fetchProp(para.getDefaultMasterStyle()); + } + } + + private void fetchProp(CTTextParagraphProperties props) { + if (props != null) { + fetcher.fetch(props, this::setValue); + } + } + + static CTTextParagraphProperties select(XSLFShape shape, int level) throws XmlException { + QName[] lvlProp = { new QName(DML_NS, "lvl" + (level + 1) + "pPr") }; + return shape.selectProperty( + CTTextParagraphProperties.class, ParagraphPropertyFetcher::parse, TX_BODY, LST_STYLE, lvlProp); + } + + static CTTextParagraphProperties parse(XMLStreamReader reader) throws XmlException { CTTextParagraph para = CTTextParagraph.Factory.parse(reader); return (para != null && para.isSetPPr()) ? para.getPPr() : null; } - public abstract boolean fetch(CTTextParagraphProperties props); + static CTTextParagraphProperties getThemeProps(XSLFShape shape, int _level) { + if (shape.isPlaceholder()) { + return null; + } + + // if it is a plain text box then take defaults from presentation.xml + @SuppressWarnings("resource") + final XMLSlideShow ppt = shape.getSheet().getSlideShow(); + + CTTextListStyle dts = ppt.getCTPresentation().getDefaultTextStyle(); + if (dts == null) { + return null; + } + + switch (_level) { + case 0: + return dts.getLvl1PPr(); + case 1: + return dts.getLvl2PPr(); + case 2: + return dts.getLvl3PPr(); + case 3: + return dts.getLvl4PPr(); + case 4: + return dts.getLvl5PPr(); + case 5: + return dts.getLvl6PPr(); + case 6: + return dts.getLvl7PPr(); + case 7: + return dts.getLvl8PPr(); + case 8: + return dts.getLvl9PPr(); + default: + return null; + } + } }
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java index 2875e0345e..eb157e82e3 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/PropertyFetcher.java @@ -30,6 +30,7 @@ import org.apache.poi.xslf.usermodel.XSLFShape; @Internal public abstract class PropertyFetcher<T> { private T _value; + private boolean isSet = false; /** * @@ -44,5 +45,10 @@ public abstract class PropertyFetcher<T> { public void setValue(T val){ _value = val; + isSet = true; + } + + public boolean isSet() { + return isSet; } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index 2045d59969..4a355fead0 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -54,8 +54,6 @@ import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.Units; import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMasterIdList; import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMasterIdListEntry; import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; @@ -281,10 +279,10 @@ public class XMLSlideShow extends POIXMLDocument slide.addRelation(null, XSLFRelation.CHART, chart); return chart; } - + /** * This method is used to create template for chart XML. - * @return Xslf chart object + * @return Xslf chart object * @since POI 4.1.0 */ public XSLFChart createChart() { @@ -593,17 +591,6 @@ public class XMLSlideShow extends POIXMLDocument return _tableStyles; } - CTTextParagraphProperties getDefaultParagraphStyle(int level) { - XmlObject[] o = _presentation.selectPath( - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + - "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + - ".//p:defaultTextStyle/a:lvl" + (level + 1) + "pPr"); - if (o.length == 1) { - return (CTTextParagraphProperties) o[0]; - } - return null; - } - @SuppressWarnings("RedundantThrows") @Override public MasterSheet<XSLFShape, XSLFTextParagraph> createMasterSheet() throws IOException { diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index 197024064e..a77ead66fa 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -492,7 +492,8 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> { * @return true if the property was fetched */ @SuppressWarnings("WeakerAccess") - protected boolean fetchShapeProperty(PropertyFetcher<?> visitor) { + @Internal + public boolean fetchShapeProperty(PropertyFetcher<?> visitor) { // try shape properties in slide if (visitor.fetch(this)) { return true; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java index 17a67794ed..7c36b1dd8e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -34,6 +35,7 @@ import org.apache.poi.util.Beta; import org.apache.poi.util.Internal; import org.apache.poi.util.Units; import org.apache.poi.xslf.model.ParagraphPropertyFetcher; +import org.apache.poi.xslf.model.ParagraphPropertyFetcher.ParaPropFetcher; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.drawingml.x2006.main.*; @@ -57,7 +59,6 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr void accept(); } - XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){ _p = p; _runs = new ArrayList<>(); @@ -150,19 +151,11 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr @Override public TextAlign getTextAlign(){ - ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetAlgn()){ - TextAlign val = TextAlign.values()[props.getAlgn().intValue() - 1]; - setValue(val); - return true; - } - return false; + return fetchParagraphProperty((props,val) -> { + if (props.isSetAlgn()) { + val.accept(TextAlign.values()[props.getAlgn().intValue() - 1]); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + }); } @Override @@ -179,19 +172,11 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr @Override public FontAlign getFontAlign(){ - ParagraphPropertyFetcher<FontAlign> fetcher = new ParagraphPropertyFetcher<FontAlign>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetFontAlgn()){ - FontAlign val = FontAlign.values()[props.getFontAlgn().intValue() - 1]; - setValue(val); - return true; - } - return false; + return fetchParagraphProperty((props,val) -> { + if (props.isSetFontAlgn()) { + val.accept(FontAlign.values()[props.getFontAlgn().intValue() - 1]); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + }); } /** @@ -220,18 +205,11 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr */ @SuppressWarnings("WeakerAccess") public String getBulletFont(){ - ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuFont()){ - setValue(props.getBuFont().getTypeface()); - return true; - } - return false; + return fetchParagraphProperty((props, val) -> { + if (props.isSetBuFont()) { + val.accept(props.getBuFont().getTypeface()); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + }); } @SuppressWarnings("WeakerAccess") @@ -246,18 +224,11 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr */ @SuppressWarnings("WeakerAccess") public String getBulletCharacter(){ - ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuChar()){ - setValue(props.getBuChar().getChar()); - return true; - } - return false; + return fetchParagraphProperty((props, val) -> { + if (props.isSetBuChar()) { + val.accept(props.getBuChar().getChar()); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + }); } @SuppressWarnings("WeakerAccess") @@ -274,23 +245,19 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr */ @SuppressWarnings("WeakerAccess") public PaintStyle getBulletFontColor(){ - final XSLFTheme theme = getParentShape().getSheet().getTheme(); - ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuClr()){ - XSLFColor c = new XSLFColor(props.getBuClr(), theme, null, _shape.getSheet()); - setValue(c.getColor()); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - Color col = fetcher.getValue(); + Color col = fetchParagraphProperty(this::fetchBulletFontColor); return (col == null) ? null : DrawPaint.createSolidPaint(col); } + private void fetchBulletFontColor(CTTextParagraphProperties props, Consumer<Color> val) { + final XSLFSheet sheet = getParentShape().getSheet(); + final XSLFTheme theme = sheet.getTheme(); + if(props.isSetBuClr()){ + XSLFColor c = new XSLFColor(props.getBuClr(), theme, null, sheet); + val.accept(c.getColor()); + } + } + @SuppressWarnings("WeakerAccess") public void setBulletFontColor(Color color) { setBulletFontColor(DrawPaint.createSolidPaint(color)); @@ -330,24 +297,19 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr */ @SuppressWarnings("WeakerAccess") public Double getBulletFontSize(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuSzPct()){ - setValue(props.getBuSzPct().getVal() * 0.001); - return true; - } - if(props.isSetBuSzPts()){ - setValue( - props.getBuSzPts().getVal() * 0.01); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + return fetchParagraphProperty(XSLFTextParagraph::fetchBulletFontSize); } + private static void fetchBulletFontSize(CTTextParagraphProperties props, Consumer<Double> val) { + if(props.isSetBuSzPct()){ + val.accept(props.getBuSzPct().getVal() * 0.001); + } + if(props.isSetBuSzPts()){ + val.accept( - props.getBuSzPts().getVal() * 0.01); + } + } + + /** * Sets the bullet size that is to be used within a paragraph. * This may be specified in two different ways, percentage spacing and font point spacing: @@ -380,45 +342,31 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr */ @SuppressWarnings("WeakerAccess") public AutoNumberingScheme getAutoNumberingScheme() { - ParagraphPropertyFetcher<AutoNumberingScheme> fetcher = new ParagraphPropertyFetcher<AutoNumberingScheme>(getIndentLevel()) { - @Override - public boolean fetch(CTTextParagraphProperties props) { - if (props.isSetBuAutoNum()) { - AutoNumberingScheme ans = AutoNumberingScheme.forOoxmlID(props.getBuAutoNum().getType().intValue()); - if (ans != null) { - setValue(ans); - return true; - } - } - return false; + return fetchParagraphProperty(XSLFTextParagraph::fetchAutoNumberingScheme); + } + + private static void fetchAutoNumberingScheme(CTTextParagraphProperties props, Consumer<AutoNumberingScheme> val) { + if (props.isSetBuAutoNum()) { + AutoNumberingScheme ans = AutoNumberingScheme.forOoxmlID(props.getBuAutoNum().getType().intValue()); + if (ans != null) { + val.accept(ans); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + } } + /** * @return the auto numbering starting number, or null if not defined */ @SuppressWarnings("WeakerAccess") public Integer getAutoNumberingStartAt() { - ParagraphPropertyFetcher<Integer> fetcher = new ParagraphPropertyFetcher<Integer>(getIndentLevel()) { - @Override - public boolean fetch(CTTextParagraphProperties props) { - if (props.isSetBuAutoNum()) { - if (props.getBuAutoNum().isSetStartAt()) { - setValue(props.getBuAutoNum().getStartAt()); - return true; - } - } - return false; + return fetchParagraphProperty((props, val) -> { + if (props.isSetBuAutoNum() && props.getBuAutoNum().isSetStartAt()) { + val.accept(props.getBuAutoNum().getStartAt()); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + }); } - @Override public void setIndent(Double indent){ if ((indent == null) && !_p.isSetPPr()) { @@ -436,22 +384,14 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr @Override public Double getIndent() { - - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetIndent()){ - setValue(Units.toPoints(props.getIndent())); - return true; - } - return false; + return fetchParagraphProperty((props, val) -> { + if (props.isSetIndent()) { + val.accept(Units.toPoints(props.getIndent())); } - }; - fetchParagraphProperty(fetcher); - - return fetcher.getValue(); + }); } + @Override public void setLeftMargin(Double leftMargin){ if (leftMargin == null && !_p.isSetPPr()) { @@ -472,21 +412,12 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr * @return the left margin (in points) of the paragraph, null if unset */ @Override - public Double getLeftMargin(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetMarL()){ - double val = Units.toPoints(props.getMarL()); - setValue(val); - return true; - } - return false; + public Double getLeftMargin() { + return fetchParagraphProperty((props, val) -> { + if (props.isSetMarL()) { + val.accept(Units.toPoints(props.getMarL())); } - }; - fetchParagraphProperty(fetcher); - // if the marL attribute is omitted, then a value of 347663 is implied - return fetcher.getValue(); + }); } @Override @@ -510,59 +441,39 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr */ @Override public Double getRightMargin(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetMarR()){ - double val = Units.toPoints(props.getMarR()); - setValue(val); - return true; - } - return false; + return fetchParagraphProperty((props, val) -> { + if (props.isSetMarR()) { + val.accept(Units.toPoints(props.getMarR())); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + }); } @Override public Double getDefaultTabSize(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetDefTabSz()){ - double val = Units.toPoints(props.getDefTabSz()); - setValue(val); - return true; - } - return false; + return fetchParagraphProperty((props, val) -> { + if (props.isSetDefTabSz()) { + val.accept(Units.toPoints(props.getDefTabSz())); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + }); } @SuppressWarnings("WeakerAccess") public double getTabStop(final int idx) { - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if (props.isSetTabLst()) { - CTTextTabStopList tabStops = props.getTabLst(); - if(idx < tabStops.sizeOfTabArray() ) { - CTTextTabStop ts = tabStops.getTabArray(idx); - double val = Units.toPoints(ts.getPos()); - setValue(val); - return true; - } - } - return false; + Double d = fetchParagraphProperty((props,val) -> fetchTabStop(idx,props,val)); + return (d == null) ? 0. : d; + } + + private static void fetchTabStop(final int idx, CTTextParagraphProperties props, Consumer<Double> val) { + if (props.isSetTabLst()) { + CTTextTabStopList tabStops = props.getTabLst(); + if(idx < tabStops.sizeOfTabArray() ) { + CTTextTabStop ts = tabStops.getTabArray(idx); + val.accept(Units.toPoints(ts.getPos())); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0. : fetcher.getValue(); + } } + @SuppressWarnings("WeakerAccess") public void addTabStop(double value){ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); @@ -650,32 +561,22 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr } private Double getSpacing(final Function<CTTextParagraphProperties,Supplier<CTTextSpacing>> getSpc) { - final ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){ - @Override - public boolean fetch(final CTTextParagraphProperties props){ - final CTTextSpacing spc = getSpc.apply(props).get(); - - if (spc == null) { - return false; - } - - if (spc.isSetSpcPct()) { - setValue( spc.getSpcPct().getVal()*0.001 ); - return true; - } - - if (spc.isSetSpcPts()) { - setValue( -spc.getSpcPts().getVal()*0.01 ); - return true; - } + return fetchParagraphProperty((props,val) -> fetchSpacing(getSpc,props,val)); + } - return false; + private static void fetchSpacing(final Function<CTTextParagraphProperties,Supplier<CTTextSpacing>> getSpc, + CTTextParagraphProperties props, Consumer<Double> val) { + final CTTextSpacing spc = getSpc.apply(props).get(); + if (spc != null) { + if (spc.isSetSpcPct()) { + val.accept( spc.getSpcPct().getVal()*0.001 ); + } else if (spc.isSetSpcPts()) { + val.accept( -spc.getSpcPts().getVal()*0.01 ); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + } } + @Override public void setIndentLevel(int level){ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); @@ -692,24 +593,19 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr * Returns whether this paragraph has bullets */ public boolean isBullet() { - ParagraphPropertyFetcher<Boolean> fetcher = new ParagraphPropertyFetcher<Boolean>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuNone()) { - setValue(false); - return true; - } - if(props.isSetBuFont() || props.isSetBuChar()){ - setValue(true); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); + Boolean b = fetchParagraphProperty(XSLFTextParagraph::fetchIsBullet); + return b == null ? false : b; + } + + private static void fetchIsBullet(CTTextParagraphProperties props, Consumer<Boolean> val) { + if (props.isSetBuNone()) { + val.accept(false); + } else if(props.isSetBuFont() || props.isSetBuChar()){ + val.accept(true); + } } + /** * * @param flag whether text in this paragraph has bullets @@ -789,7 +685,8 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr * @return master style text paragraph properties, or <code>null</code> if * there are no master slides or the master slides do not contain a text paragraph */ - private CTTextParagraphProperties getDefaultMasterStyle(){ + @Internal + public CTTextParagraphProperties getDefaultMasterStyle(){ CTPlaceholder ph = _shape.getPlaceholderDetails().getCTPlaceholder(false); String defaultStyleSelector; switch(ph == null ? -1 : ph.getType().intValue()) { @@ -837,49 +734,11 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr return null; } - private void fetchParagraphProperty(final ParagraphPropertyFetcher<?> visitor){ + private <T> T fetchParagraphProperty(ParaPropFetcher<T> fetcher){ final XSLFTextShape shape = getParentShape(); - final XSLFSheet sheet = shape.getSheet(); - - if (!(sheet instanceof XSLFSlideMaster)) { - if (_p.isSetPPr() && visitor.fetch(_p.getPPr())) { - return; - } - - if (shape.fetchShapeProperty(visitor)) { - return; - } - - if (fetchThemeProperty(visitor)) { - return; - } - } - - fetchMasterProperty(visitor); - } - - void fetchMasterProperty(final ParagraphPropertyFetcher<?> visitor) { - // defaults for placeholders are defined in the slide master - final CTTextParagraphProperties defaultProps = getDefaultMasterStyle(); - // TODO: determine master shape - if (defaultProps != null) { - visitor.fetch(defaultProps); - } + return new ParagraphPropertyFetcher<>(this, fetcher).fetchProperty(shape); } - boolean fetchThemeProperty(final ParagraphPropertyFetcher<?> visitor) { - final XSLFTextShape shape = getParentShape(); - - if (shape.isPlaceholder()) { - return false; - } - - // if it is a plain text box then take defaults from presentation.xml - @SuppressWarnings("resource") - final XMLSlideShow ppt = shape.getSheet().getSlideShow(); - final CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel()); - return themeProps != null && visitor.fetch(themeProps); - } void copy(XSLFTextParagraph other){ if (other == this) { @@ -1074,25 +933,22 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr @Override public List<XSLFTabStop> getTabStops() { - ParagraphPropertyFetcher<List<XSLFTabStop>> fetcher = new ParagraphPropertyFetcher<List<XSLFTabStop>>(getIndentLevel()){ - @Override - public boolean fetch(CTTextParagraphProperties props) { - if (props.isSetTabLst()) { - final List<XSLFTabStop> list = new ArrayList<>(); - //noinspection deprecation - for (final CTTextTabStop ta : props.getTabLst().getTabArray()) { - list.add(new XSLFTabStop(ta)); - } - setValue(list); - return true; - } - return false; + return fetchParagraphProperty(XSLFTextParagraph::fetchTabStops); + } + + private static void fetchTabStops(CTTextParagraphProperties props, Consumer<List<XSLFTabStop>> val) { + if (props.isSetTabLst()) { + final List<XSLFTabStop> list = new ArrayList<>(); + //noinspection deprecation + for (final CTTextTabStop ta : props.getTabLst().getTabArray()) { + list.add(new XSLFTabStop(ta)); } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); + val.accept(list); + } } + + @Override public void addTabStops(double positionInPoints, TabStopType tabStopType) { final XSLFSheet sheet = getParentShape().getSheet(); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java index 16df8cecd7..1c3890a159 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java @@ -17,6 +17,7 @@ package org.apache.poi.xslf.usermodel; import java.awt.Color; +import java.util.function.Consumer; import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.common.usermodel.fonts.FontFamily; @@ -34,6 +35,7 @@ import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; 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.CTFontCollection; @@ -126,39 +128,35 @@ public class XSLFTextRun implements TextRun { @Override public PaintStyle getFontColor(){ - final boolean hasPlaceholder = getParagraph().getParentShape().getPlaceholder() != null; - CharacterPropertyFetcher<PaintStyle> fetcher = new CharacterPropertyFetcher<PaintStyle>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props == null) { - return false; - } + XSLFShape shape = getParagraph().getParentShape(); + final boolean hasPlaceholder = shape.getPlaceholder() != null; + return fetchCharacterProperty((props, val) -> fetchFontColor(props, val, shape, hasPlaceholder)); + } - XSLFShape shape = _p.getParentShape(); - CTShapeStyle style = shape.getSpStyle(); - CTSchemeColor phClr = null; - if (style != null && style.getFontRef() != null) { - phClr = style.getFontRef().getSchemeClr(); - } + private static void fetchFontColor(CTTextCharacterProperties props, Consumer<PaintStyle> val, XSLFShape shape, boolean hasPlaceholder) { + if (props == null) { + return; + } - XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props); - XSLFSheet sheet = shape.getSheet(); - PackagePart pp = sheet.getPackagePart(); - XSLFTheme theme = sheet.getTheme(); - PaintStyle ps = shape.selectPaint(fp, phClr, pp, theme, hasPlaceholder); + CTShapeStyle style = shape.getSpStyle(); + CTSchemeColor phClr = null; + if (style != null && style.getFontRef() != null) { + phClr = style.getFontRef().getSchemeClr(); + } - if (ps != null) { - setValue(ps); - return true; - } + XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props); + XSLFSheet sheet = shape.getSheet(); + PackagePart pp = sheet.getPackagePart(); + XSLFTheme theme = sheet.getTheme(); + PaintStyle ps = shape.selectPaint(fp, phClr, pp, theme, hasPlaceholder); - return false; - } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue(); + if (ps != null) { + val.accept(ps); + } } + + @Override public void setFontSize(Double fontSize){ CTTextCharacterProperties rPr = getRPr(true); @@ -189,18 +187,12 @@ public class XSLFTextRun implements TextRun { } } - final CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetSz()) { - setValue(props.getSz()*0.01); - return true; - } - return false; + Double d = fetchCharacterProperty((props, val) -> { + if (props.isSetSz()) { + val.accept(props.getSz()*0.01); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? null : fetcher.getValue()*scale; + }); + return d == null ? null : d*scale; } /** @@ -209,19 +201,12 @@ public class XSLFTextRun implements TextRun { */ @SuppressWarnings("WeakerAccess") public double getCharacterSpacing(){ - - CharacterPropertyFetcher<Double> fetcher = new CharacterPropertyFetcher<Double>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetSpc()) { - setValue(props.getSpc()*0.01); - return true; - } - return false; + Double d = fetchCharacterProperty((props, val) -> { + if (props.isSetSpc()) { + val.accept(props.getSpc()*0.01); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); + }); + return d == null ? 0 : d; } /** @@ -300,34 +285,22 @@ public class XSLFTextRun implements TextRun { @Override public boolean isStrikethrough() { - CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if(props != null && props.isSetStrike()) { - setValue(props.getStrike() != STTextStrikeType.NO_STRIKE); - return true; - } - return false; + Boolean b = fetchCharacterProperty((props, val) -> { + if (props.isSetStrike()) { + val.accept(props.getStrike() != STTextStrikeType.NO_STRIKE); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); + }); + return b != null && b; } @Override public boolean isSuperscript() { - CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetBaseline()) { - setValue(props.getBaseline() > 0); - return true; - } - return false; + Boolean b = fetchCharacterProperty((props, val) -> { + if (props.isSetBaseline()) { + val.accept(props.getBaseline() > 0); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); + }); + return b != null && b; } /** @@ -366,18 +339,12 @@ public class XSLFTextRun implements TextRun { @Override public boolean isSubscript() { - CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetBaseline()) { - setValue(props.getBaseline() < 0); - return true; - } - return false; + Boolean b = fetchCharacterProperty((props, val) -> { + if (props.isSetBaseline()) { + val.accept(props.getBaseline() < 0); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); + }); + return b != null && b; } /** @@ -385,19 +352,12 @@ public class XSLFTextRun implements TextRun { */ @Override public TextCap getTextCap() { - CharacterPropertyFetcher<TextCap> fetcher = new CharacterPropertyFetcher<TextCap>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetCap()) { - int idx = props.getCap().intValue() - 1; - setValue(TextCap.values()[idx]); - return true; - } - return false; + TextCap textCap = fetchCharacterProperty((props, val) -> { + if (props.isSetCap()) { + val.accept(TextCap.values()[props.getCap().intValue() - 1]); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? TextCap.NONE : fetcher.getValue(); + }); + return textCap == null ? TextCap.NONE : textCap; } @Override @@ -406,40 +366,29 @@ public class XSLFTextRun implements TextRun { } @Override - public boolean isBold(){ - CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetB()) { - setValue(props.getB()); - return true; - } - return false; + public boolean isBold() { + Boolean b = fetchCharacterProperty((props, val) -> { + if (props.isSetB()) { + val.accept(props.getB()); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); + }); + return b != null && b; } + @Override public void setItalic(boolean italic){ getRPr(true).setI(italic); } @Override - public boolean isItalic(){ - CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetI()) { - setValue(props.getI()); - return true; - } - return false; + public boolean isItalic() { + Boolean b = fetchCharacterProperty((props, val) -> { + if (props.isSetI()) { + val.accept(props.getI()); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); + }); + return b != null && b; } @Override @@ -449,18 +398,12 @@ public class XSLFTextRun implements TextRun { @Override public boolean isUnderlined(){ - CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - if (props != null && props.isSetU()) { - setValue(props.getU() != STTextUnderlineType.NONE); - return true; - } - return false; + Boolean b = fetchCharacterProperty((props, val) -> { + if (props.isSetU()) { + val.accept(props.getU() != STTextUnderlineType.NONE); } - }; - fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); + }); + return b != null && b; } /** @@ -469,7 +412,8 @@ public class XSLFTextRun implements TextRun { * @param create if true, create an empty character properties object if it doesn't exist * @return the character properties or null if create was false and the properties haven't exist */ - protected CTTextCharacterProperties getRPr(boolean create) { + @Internal + public CTTextCharacterProperties getRPr(boolean create) { if (_r instanceof CTTextField) { CTTextField tf = (CTTextField)_r; if (tf.isSetRPr()) { @@ -527,23 +471,9 @@ public class XSLFTextRun implements TextRun { return new XSLFHyperlink(hl, _p.getParentShape().getSheet()); } - private void fetchCharacterProperty(final CharacterPropertyFetcher<?> visitor){ - XSLFTextShape shape = _p.getParentShape(); - - CTTextCharacterProperties rPr = getRPr(false); - if (rPr != null && visitor.fetch(rPr)) { - return; - } - - if (shape.fetchShapeProperty(visitor)) { - return; - } - - if (_p.fetchThemeProperty(visitor)) { - return; - } - - _p.fetchMasterProperty(visitor); + private <T> T fetchCharacterProperty(CharPropFetcher<T> fetcher){ + final XSLFTextShape shape = _p.getParentShape(); + return new CharacterPropertyFetcher<>(this, fetcher).fetchProperty(shape); } void copy(XSLFTextRun r){ @@ -742,20 +672,12 @@ public class XSLFTextRun implements TextRun { return getCTTextFont(getRPr(true), true); } - CharacterPropertyFetcher<CTTextFont> visitor = new CharacterPropertyFetcher<CTTextFont>(_p.getIndentLevel()){ - @Override - public boolean fetch(CTTextCharacterProperties props){ - CTTextFont font = getCTTextFont(props, false); - if (font == null) { - return false; - } - setValue(font); - return true; + return fetchCharacterProperty((props, val) -> { + CTTextFont font = getCTTextFont(props, false); + if (font != null) { + val.accept(font); } - }; - fetchCharacterProperty(visitor); - - return visitor.getValue(); + }); } private CTTextFont getCTTextFont(CTTextCharacterProperties props, boolean create) { |