diff --git a/src/java/org/apache/poi/sl/draw/DrawTextFragment.java b/src/java/org/apache/poi/sl/draw/DrawTextFragment.java index 178983d5e..0eceb9364 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextFragment.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextFragment.java @@ -69,11 +69,20 @@ public class DrawTextFragment implements Drawable { /** * @return full height of this text run which is sum of ascent, descent and leading */ - public float getHeight(){ - double h = Math.ceil(layout.getAscent()) + Math.ceil(layout.getDescent()) + layout.getLeading(); + public float getHeight(){ + double h = Math.ceil(layout.getAscent()) + Math.ceil(layout.getDescent()) + getLeading(); return (float)h; } + /** + * @return the leading height before/after a text line + */ + public float getLeading() { + // fix invalid leadings (leading == 0) by fallback to descent + double l = layout.getLeading(); + return (float)(l == 0 ? layout.getDescent() : l); + } + /** * * @return width if this text run diff --git a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java index d978b3c37..10d4edfd6 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java @@ -215,6 +215,10 @@ public class DrawTextParagraph implements Drawable { y = penY - y; } + public float getFirstLineLeading() { + return (lines.isEmpty()) ? 0 : lines.get(0).getLeading(); + } + public float getFirstLineHeight() { return (lines.isEmpty()) ? 0 : lines.get(0).getHeight(); } @@ -253,7 +257,8 @@ public class DrawTextParagraph implements Drawable { for (;;) { int startIndex = measurer.getPosition(); - double wrappingWidth = getWrappingWidth(lines.size() == 0, graphics) + 1; // add a pixel to compensate rounding errors + // add a pixel to compensate rounding errors + double wrappingWidth = getWrappingWidth(lines.isEmpty(), graphics) + 1; // shape width can be smaller that the sum of insets (this was proved by a test file) if(wrappingWidth < 0) { wrappingWidth = 1; diff --git a/src/java/org/apache/poi/sl/draw/DrawTextShape.java b/src/java/org/apache/poi/sl/draw/DrawTextShape.java index 89f85a2f0..cffffb4a8 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextShape.java @@ -137,10 +137,7 @@ public class DrawTextShape extends DrawSimpleShape { DrawFactory fact = DrawFactory.getInstance(graphics); double y0 = y; - //noinspection RedundantCast - @SuppressWarnings("cast") - Iterator> paragraphs = - (Iterator>) getShape().iterator(); + Iterator> paragraphs = getShape().iterator(); boolean isFirstLine = true; for (int autoNbrIdx=0; paragraphs.hasNext(); autoNbrIdx++){ @@ -158,7 +155,9 @@ public class DrawTextShape extends DrawSimpleShape { dp.setAutoNumberingIdx(autoNbrIdx); dp.breakText(graphics); - if (!isFirstLine) { + if (isFirstLine) { + y += dp.getFirstLineLeading(); + } else { // the amount of vertical white space before the paragraph Double spaceBefore = p.getSpaceBefore(); if (spaceBefore == null) spaceBefore = 0d; @@ -221,7 +220,7 @@ public class DrawTextShape extends DrawSimpleShape { } @Override - protected TextShape getShape() { - return (TextShape)shape; + protected TextShape> getShape() { + return (TextShape>)shape; } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java index 91b0869b8..ad979f1d6 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java @@ -67,6 +67,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape } } + @Override public Iterator iterator(){ return getTextParagraphs().iterator(); } @@ -75,7 +76,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public String getText() { StringBuilder out = new StringBuilder(); for (XSLFTextParagraph p : _paragraphs) { - if (out.length() > 0) out.append('\n'); + if (out.length() > 0) { + out.append('\n'); + } out.append(p.getText()); } return out.toString(); @@ -109,7 +112,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape @Override public XSLFTextRun appendText(String text, boolean newParagraph) { - if (text == null) return null; + if (text == null) { + return null; + } // copy properties from last paragraph / textrun or paragraph end marker CTTextParagraphProperties otherPPr = null; @@ -202,7 +207,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { if(anchor == null) { - if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor(); + if(bodyPr.isSetAnchor()) { + bodyPr.unsetAnchor(); + } } else { bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); } @@ -212,6 +219,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape @Override public VerticalAlignment getVerticalAlignment(){ PropertyFetcher fetcher = new TextBodyPropertyFetcher(){ + @Override public boolean fetch(CTTextBodyProperties props){ if(props.isSetAnchor()){ int val = props.getAnchor().intValue(); @@ -230,7 +238,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { if (isCentered == null) { - if (bodyPr.isSetAnchorCtr()) bodyPr.unsetAnchorCtr(); + if (bodyPr.isSetAnchorCtr()) { + bodyPr.unsetAnchorCtr(); + } } else { bodyPr.setAnchorCtr(isCentered); } @@ -240,6 +250,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape @Override public boolean isHorizontalCentered(){ PropertyFetcher fetcher = new TextBodyPropertyFetcher(){ + @Override public boolean fetch(CTTextBodyProperties props){ if(props.isSetAnchorCtr()){ setValue(props.getAnchorCtr()); @@ -257,7 +268,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { if(orientation == null) { - if(bodyPr.isSetVert()) bodyPr.unsetVert(); + if(bodyPr.isSetVert()) { + bodyPr.unsetVert(); + } } else { bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1)); } @@ -315,6 +328,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape */ public double getBottomInset(){ PropertyFetcher fetcher = new TextBodyPropertyFetcher(){ + @Override public boolean fetch(CTTextBodyProperties props){ if(props.isSetBIns()){ double val = Units.toPoints(props.getBIns()); @@ -338,6 +352,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape */ public double getLeftInset(){ PropertyFetcher fetcher = new TextBodyPropertyFetcher(){ + @Override public boolean fetch(CTTextBodyProperties props){ if(props.isSetLIns()){ double val = Units.toPoints(props.getLIns()); @@ -361,6 +376,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape */ public double getRightInset(){ PropertyFetcher fetcher = new TextBodyPropertyFetcher(){ + @Override public boolean fetch(CTTextBodyProperties props){ if(props.isSetRIns()){ double val = Units.toPoints(props.getRIns()); @@ -383,6 +399,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape */ public double getTopInset(){ PropertyFetcher fetcher = new TextBodyPropertyFetcher(){ + @Override public boolean fetch(CTTextBodyProperties props){ if(props.isSetTIns()){ double val = Units.toPoints(props.getTIns()); @@ -406,8 +423,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public void setBottomInset(double margin){ CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { - if(margin == -1) bodyPr.unsetBIns(); - else bodyPr.setBIns(Units.toEMU(margin)); + if(margin == -1) { + bodyPr.unsetBIns(); + } else { + bodyPr.setBIns(Units.toEMU(margin)); + } } } @@ -420,8 +440,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public void setLeftInset(double margin){ CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { - if(margin == -1) bodyPr.unsetLIns(); - else bodyPr.setLIns(Units.toEMU(margin)); + if(margin == -1) { + bodyPr.unsetLIns(); + } else { + bodyPr.setLIns(Units.toEMU(margin)); + } } } @@ -434,8 +457,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public void setRightInset(double margin){ CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { - if(margin == -1) bodyPr.unsetRIns(); - else bodyPr.setRIns(Units.toEMU(margin)); + if(margin == -1) { + bodyPr.unsetRIns(); + } else { + bodyPr.setRIns(Units.toEMU(margin)); + } } } @@ -448,8 +474,11 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public void setTopInset(double margin){ CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { - if(margin == -1) bodyPr.unsetTIns(); - else bodyPr.setTIns(Units.toEMU(margin)); + if(margin == -1) { + bodyPr.unsetTIns(); + } else { + bodyPr.setTIns(Units.toEMU(margin)); + } } } @@ -470,6 +499,7 @@ public abstract class XSLFTextShape extends XSLFSimpleShape @Override public boolean getWordWrap(){ PropertyFetcher fetcher = new TextBodyPropertyFetcher(){ + @Override public boolean fetch(CTTextBodyProperties props){ if(props.isSetWrap()){ setValue(props.getWrap() == STTextWrappingType.SQUARE); @@ -500,9 +530,15 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public void setTextAutofit(TextAutofit value){ CTTextBodyProperties bodyPr = getTextBodyPr(true); if (bodyPr != null) { - if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit(); - if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit(); - if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit(); + if(bodyPr.isSetSpAutoFit()) { + bodyPr.unsetSpAutoFit(); + } + if(bodyPr.isSetNoAutofit()) { + bodyPr.unsetNoAutofit(); + } + if(bodyPr.isSetNormAutofit()) { + bodyPr.unsetNormAutofit(); + } switch(value){ case NONE: bodyPr.addNewNoAutofit(); break; @@ -519,9 +555,13 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public TextAutofit getTextAutofit(){ CTTextBodyProperties bodyPr = getTextBodyPr(); if (bodyPr != null) { - if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE; - else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL; - else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE; + if(bodyPr.isSetNoAutofit()) { + return TextAutofit.NONE; + } else if (bodyPr.isSetNormAutofit()) { + return TextAutofit.NORMAL; + } else if (bodyPr.isSetSpAutoFit()) { + return TextAutofit.SHAPE; + } } return TextAutofit.NORMAL; } @@ -551,7 +591,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape public Placeholder getTextType(){ CTPlaceholder ph = getCTPlaceholder(); - if (ph == null) return null; + if (ph == null) { + return null; + } int val = ph.getType().intValue(); return Placeholder.lookupOoxml(val); @@ -571,12 +613,15 @@ public abstract class XSLFTextShape extends XSLFSimpleShape */ public Rectangle2D resizeToFitText(){ Rectangle2D anchor = getAnchor(); - if(anchor.getWidth() == 0.) throw new POIXMLException( - "Anchor of the shape was not set."); + + if(anchor.getWidth() == 0.) { + throw new POIXMLException("Anchor of the shape was not set."); + } double height = getTextHeight(); height += 1; // add a pixel to compensate rounding errors - anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height); + Insets2D insets = getInsets(); + anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height+insets.top+insets.bottom); setAnchor(anchor); return anchor; @@ -596,7 +641,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape thisTB.setBodyPr((CTTextBodyProperties)otherTB.getBodyPr().copy()); - if (thisTB.isSetLstStyle()) thisTB.unsetLstStyle(); + if (thisTB.isSetLstStyle()) { + thisTB.unsetLstStyle(); + } if (otherTB.isSetLstStyle()) { thisTB.setLstStyle((CTTextListStyle)otherTB.getLstStyle().copy()); } @@ -665,7 +712,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape @Override public TextPlaceholder getTextPlaceholder() { Placeholder ph = getTextType(); - if (ph == null) return TextPlaceholder.BODY; + if (ph == null) { + return TextPlaceholder.BODY; + } switch (ph) { case BODY: return TextPlaceholder.BODY; case TITLE: return TextPlaceholder.TITLE; @@ -679,9 +728,9 @@ public abstract class XSLFTextShape extends XSLFSimpleShape * Helper method to allow subclasses to provide their own text paragraph * * @param p the xml reference - * + * * @return a new text paragraph - * + * * @since POI 3.15-beta2 */ protected XSLFTextParagraph newTextParagraph(CTTextParagraph p) { diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java index d7b4e2773..96cea8034 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java @@ -329,7 +329,8 @@ implements TextShape { double height = getTextHeight(); height += 1; // add a pixel to compensate rounding errors - anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height); + Insets2D insets = getInsets(); + anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height+insets.top+insets.bottom); setAnchor(anchor); return anchor;