You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2016/08/19 20:57:56 UTC

svn commit: r1756967 [2/3] - in /poi/branches/hssf_cryptoapi: ./ sonar/ sonar/examples/ sonar/excelant/ sonar/main/ sonar/ooxml-schema-encryption/ sonar/ooxml-schema-security/ sonar/ooxml-schema/ sonar/ooxml/ sonar/scratchpad/ src/ooxml/java/org/apache...

Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java?rev=1756967&r1=1756966&r2=1756967&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java Fri Aug 19 20:57:56 2016
@@ -1,1071 +1,1079 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-package org.apache.poi.xslf.usermodel;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.poi.sl.draw.DrawPaint;
-import org.apache.poi.sl.usermodel.AutoNumberingScheme;
-import org.apache.poi.sl.usermodel.PaintStyle;
-import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
-import org.apache.poi.sl.usermodel.TextParagraph;
-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.xmlbeans.XmlCursor;
-import org.apache.xmlbeans.XmlObject;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextAutonumberBullet;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePercent;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePoint;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharBullet;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStop;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStopList;
-import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
-import org.openxmlformats.schemas.drawingml.x2006.main.STTextAutonumberScheme;
-import org.openxmlformats.schemas.drawingml.x2006.main.STTextFontAlignType;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
-import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
-
-/**
- * Represents a paragraph of text within the containing text body.
- * The paragraph is the highest level text separation mechanism.
- *
- * @since POI-3.8
- */
-@Beta
-public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagraph,XSLFTextRun> {
-    private final CTTextParagraph _p;
-    private final List<XSLFTextRun> _runs;
-    private final XSLFTextShape _shape;
-
-    XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
-        _p = p;
-        _runs = new ArrayList<XSLFTextRun>();
-        _shape = shape;
-
-        for(XmlObject ch : _p.selectPath("*")){
-            if(ch instanceof CTRegularTextRun){
-                CTRegularTextRun r = (CTRegularTextRun)ch;
-                _runs.add(newTextRun(r));
-            } else if (ch instanceof CTTextLineBreak){
-                CTTextLineBreak br = (CTTextLineBreak)ch;
-                CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
-                r.setRPr(br.getRPr());
-                r.setT("\n");
-                _runs.add(newTextRun(r));
-            } else if (ch instanceof CTTextField){
-                CTTextField f = (CTTextField)ch;
-                CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
-                r.setRPr(f.getRPr());
-                r.setT(f.getT());
-                _runs.add(newTextRun(r));
-            }
-        }
-    }
-
-    public String getText(){
-        StringBuilder out = new StringBuilder();
-        for (XSLFTextRun r : _runs) {
-            out.append(r.getRawText());
-        }
-        return out.toString();
-    }
-
-    String getRenderableText(){
-        StringBuilder out = new StringBuilder();
-        for (XSLFTextRun r : _runs) {
-            out.append(r.getRenderableText());
-        }
-        return out.toString();
-    }
-
-    @Internal
-    public CTTextParagraph getXmlObject(){
-        return _p;
-    }
-
-    public XSLFTextShape getParentShape() {
-        return _shape;
-
-    }
-
-    @Override
-    public List<XSLFTextRun> getTextRuns(){
-        return _runs;
-    }
-
-    public Iterator<XSLFTextRun> iterator(){
-        return _runs.iterator();
-    }
-
-    /**
-     * Add a new run of text
-     *
-     * @return a new run of text
-     */
-    public XSLFTextRun addNewTextRun(){
-        CTRegularTextRun r = _p.addNewR();
-        CTTextCharacterProperties rPr = r.addNewRPr();
-        rPr.setLang("en-US");
-        XSLFTextRun run = newTextRun(r);
-        _runs.add(run);
-        return run;
-    }
-
-    /**
-     * Insert a line break
-     *
-     * @return text run representing this line break ('\n')
-     */
-    public XSLFTextRun addLineBreak(){
-        CTTextLineBreak br = _p.addNewBr();
-        CTTextCharacterProperties brProps = br.addNewRPr();
-        if(_runs.size() > 0){
-            // by default line break has the font size of the last text run
-            CTTextCharacterProperties prevRun = _runs.get(_runs.size() - 1).getRPr(true);
-            brProps.set(prevRun);
-        }
-        CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
-        r.setRPr(brProps);
-        r.setT("\n");
-        XSLFTextRun run = new XSLFLineBreak(r, this, brProps);
-        _runs.add(run);
-        return run;
-    }
-
-    @Override
-    public TextAlign getTextAlign(){
-        ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetAlgn()){
-                    TextAlign val = TextAlign.values()[props.getAlgn().intValue() - 1];
-                    setValue(val);
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    @Override
-    public void setTextAlign(TextAlign align) {
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        if(align == null) {
-            if(pr.isSetAlgn()) pr.unsetAlgn();
-        } else {
-            pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1));
-        }
-    }
-
-    @Override
-    public FontAlign getFontAlign(){
-        ParagraphPropertyFetcher<FontAlign> fetcher = new ParagraphPropertyFetcher<FontAlign>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetFontAlgn()){
-                    FontAlign val = FontAlign.values()[props.getFontAlgn().intValue() - 1];
-                    setValue(val);
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    /**
-     * Specifies the font alignment that is to be applied to the paragraph.
-     * Possible values for this include auto, top, center, baseline and bottom.
-     * see {@link org.apache.poi.sl.usermodel.TextParagraph.FontAlign}.
-     *
-     * @param align font align
-     */
-    public void setFontAlign(FontAlign align){
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        if(align == null) {
-            if(pr.isSetFontAlgn()) pr.unsetFontAlgn();
-        } else {
-            pr.setFontAlgn(STTextFontAlignType.Enum.forInt(align.ordinal() + 1));
-        }
-    }
-
-    
-
-    /**
-     * @return the font to be used on bullet characters within a given paragraph
-     */
-    public String getBulletFont(){
-        ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetBuFont()){
-                    setValue(props.getBuFont().getTypeface());
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    public void setBulletFont(String typeface){
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        CTTextFont font = pr.isSetBuFont() ? pr.getBuFont() : pr.addNewBuFont();
-        font.setTypeface(typeface);
-    }
-
-    /**
-     * @return the character to be used in place of the standard bullet point
-     */
-    public String getBulletCharacter(){
-        ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetBuChar()){
-                    setValue(props.getBuChar().getChar());
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    public void setBulletCharacter(String str){
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        CTTextCharBullet c = pr.isSetBuChar() ? pr.getBuChar() : pr.addNewBuChar();
-        c.setChar(str);
-    }
-
-    /**
-     *
-     * @return the color of bullet characters within a given paragraph.
-     * A <code>null</code> value means to use the text font color.
-     */
-    public PaintStyle getBulletFontColor(){
-        final XSLFTheme theme = getParentShape().getSheet().getTheme();
-        ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetBuClr()){
-                    XSLFColor c = new XSLFColor(props.getBuClr(), theme, null);
-                    setValue(c.getColor());
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        Color col = fetcher.getValue();
-        return (col == null) ? null : DrawPaint.createSolidPaint(col);
-    }
-
-    public void setBulletFontColor(Color color) {
-        setBulletFontColor(DrawPaint.createSolidPaint(color));
-    }
-    
-    
-    /**
-     * Set the color to be used on bullet characters within a given paragraph.
-     *
-     * @param color the bullet color
-     */
-    public void setBulletFontColor(PaintStyle color) {
-        if (!(color instanceof SolidPaint)) {
-            throw new IllegalArgumentException("Currently XSLF only supports SolidPaint");
-        }
-
-        // TODO: implement setting bullet color to null
-        SolidPaint sp = (SolidPaint)color;
-        Color col = DrawPaint.applyColorTransform(sp.getSolidColor());
-        
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr();
-        CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr();
-        clr.setVal(new byte[]{(byte) col.getRed(), (byte) col.getGreen(), (byte) col.getBlue()});
-    }
-
-    /**
-     * Returns 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:
-     * <p>
-     * If bulletSize >= 0, then bulletSize is a percentage of the font size.
-     * If bulletSize < 0, then it specifies the size in points
-     * </p>
-     *
-     * @return the bullet size
-     */
-    public Double getBulletFontSize(){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            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();
-    }
-
-    /**
-     * 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:
-     * <p>
-     * If bulletSize >= 0, then bulletSize is a percentage of the font size.
-     * If bulletSize < 0, then it specifies the size in points
-     * </p>
-     */
-    public void setBulletFontSize(double bulletSize){
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-
-        if(bulletSize >= 0) {
-            CTTextBulletSizePercent pt = pr.isSetBuSzPct() ? pr.getBuSzPct() : pr.addNewBuSzPct();
-            pt.setVal((int)(bulletSize*1000));
-            if(pr.isSetBuSzPts()) pr.unsetBuSzPts();
-        } else {
-            CTTextBulletSizePoint pt = pr.isSetBuSzPts() ? pr.getBuSzPts() : pr.addNewBuSzPts();
-            pt.setVal((int)(-bulletSize*100));
-            if(pr.isSetBuSzPct()) pr.unsetBuSzPct();
-        }
-   }
-
-    /**
-     * @return the auto numbering scheme, or null if not defined
-     */
-    public AutoNumberingScheme getAutoNumberingScheme() {
-        ParagraphPropertyFetcher<AutoNumberingScheme> fetcher = new ParagraphPropertyFetcher<AutoNumberingScheme>(getIndentLevel()) {
-            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;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    /**
-     * @return the auto numbering starting number, or null if not defined
-     */
-    public Integer getAutoNumberingStartAt() {
-        ParagraphPropertyFetcher<Integer> fetcher = new ParagraphPropertyFetcher<Integer>(getIndentLevel()) {
-            public boolean fetch(CTTextParagraphProperties props) {
-                if (props.isSetBuAutoNum()) {
-                    if (props.getBuAutoNum().isSetStartAt()) {
-                        setValue(props.getBuAutoNum().getStartAt());
-                        return true;
-                    }
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-    
-    
-    @Override
-    public void setIndent(Double indent){
-        if ((indent == null) && !_p.isSetPPr()) return;
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        if(indent == null) {
-            if(pr.isSetIndent()) pr.unsetIndent();
-        } else {
-            pr.setIndent(Units.toEMU(indent));
-        }
-    }
-
-    @Override
-    public Double getIndent() {
-
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetIndent()){
-                    setValue(Units.toPoints(props.getIndent()));
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-
-        return fetcher.getValue();
-    }
-
-    @Override
-    public void setLeftMargin(Double leftMargin){
-        if (leftMargin == null && !_p.isSetPPr()) return;
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        if (leftMargin == null) {
-            if(pr.isSetMarL()) pr.unsetMarL();
-        } else {
-            pr.setMarL(Units.toEMU(leftMargin));
-        }
-
-    }
-
-    /**
-     * @return the left margin (in points) of the paragraph, null if unset
-     */
-    @Override
-    public Double getLeftMargin(){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetMarL()){
-                    double val = Units.toPoints(props.getMarL());
-                    setValue(val);
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        // if the marL attribute is omitted, then a value of 347663 is implied
-        return fetcher.getValue();
-    }
-
-    @Override
-    public void setRightMargin(Double rightMargin){
-        if (rightMargin == null && !_p.isSetPPr()) return;
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        if(rightMargin == null) {
-            if(pr.isSetMarR()) pr.unsetMarR();
-        } else {
-            pr.setMarR(Units.toEMU(rightMargin));
-        }
-    }
-
-    /**
-     *
-     * @return the right margin of the paragraph, null if unset
-     */
-    @Override
-    public Double getRightMargin(){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetMarR()){
-                    double val = Units.toPoints(props.getMarR());
-                    setValue(val);
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    @Override
-    public Double getDefaultTabSize(){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetDefTabSz()){
-                    double val = Units.toPoints(props.getDefTabSz());
-                    setValue(val);
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    public double getTabStop(final int idx){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            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;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue() == null ? 0. : fetcher.getValue();
-    }
-
-    public void addTabStop(double value){
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        CTTextTabStopList tabStops = pr.isSetTabLst() ? pr.getTabLst() : pr.addNewTabLst();
-        tabStops.addNewTab().setPos(Units.toEMU(value));
-    }
-
-    @Override
-    public void setLineSpacing(Double lineSpacing){
-        if (lineSpacing == null && !_p.isSetPPr()) return;
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        if(lineSpacing == null) {
-            if (pr.isSetLnSpc()) pr.unsetLnSpc();
-        } else {
-            CTTextSpacing spc = (pr.isSetLnSpc()) ? pr.getLnSpc() : pr.addNewLnSpc();
-            if (lineSpacing >= 0) {
-                (spc.isSetSpcPct() ? spc.getSpcPct() : spc.addNewSpcPct()).setVal((int)(lineSpacing*1000));
-                if (spc.isSetSpcPts()) spc.unsetSpcPts();
-            } else {
-                (spc.isSetSpcPts() ? spc.getSpcPts() : spc.addNewSpcPts()).setVal((int)(-lineSpacing*100));
-                if (spc.isSetSpcPct()) spc.unsetSpcPct();
-            }
-        }
-    }
-
-    @Override
-    public Double getLineSpacing(){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetLnSpc()){
-                    CTTextSpacing spc = props.getLnSpc();
-
-                    if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
-                    else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-
-        Double lnSpc = fetcher.getValue();
-        if (lnSpc != null && lnSpc > 0) {
-            // check if the percentage value is scaled
-            CTTextNormalAutofit normAutofit = getParentShape().getTextBodyPr().getNormAutofit();
-            if(normAutofit != null) {
-                double scale = 1 - (double)normAutofit.getLnSpcReduction() / 100000;
-                lnSpc *= scale;
-            }
-        }
-        
-        return lnSpc;
-    }
-
-    @Override
-    public void setSpaceBefore(Double spaceBefore){
-        if (spaceBefore == null && !_p.isSetPPr()) {
-            return;
-        }
-
-        // unset the space before on null input
-        if (spaceBefore == null) {
-            if(_p.getPPr().isSetSpcBef()) {
-                _p.getPPr().unsetSpcBef();
-            }
-            return;
-        }
-
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
-
-        if(spaceBefore >= 0) {
-            spc.addNewSpcPct().setVal((int)(spaceBefore*1000));
-        } else {
-            spc.addNewSpcPts().setVal((int)(-spaceBefore*100));
-        }
-        pr.setSpcBef(spc);
-    }
-
-    @Override
-    public Double getSpaceBefore(){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetSpcBef()){
-                    CTTextSpacing spc = props.getSpcBef();
-
-                    if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
-                    else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-
-        return fetcher.getValue();
-    }
-
-    @Override
-    public void setSpaceAfter(Double spaceAfter){
-        if (spaceAfter == null && !_p.isSetPPr()) {
-            return;
-        }
-
-        // unset the space before on null input
-        if (spaceAfter == null) {
-            if(_p.getPPr().isSetSpcAft()) {
-                _p.getPPr().unsetSpcAft();
-            }
-            return;
-        }
-
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
-
-        if(spaceAfter >= 0) {
-            spc.addNewSpcPct().setVal((int)(spaceAfter*1000));
-        } else {
-            spc.addNewSpcPts().setVal((int)(-spaceAfter*100));
-        }
-        pr.setSpcAft(spc);
-    }
-
-    @Override
-    public Double getSpaceAfter(){
-        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
-            public boolean fetch(CTTextParagraphProperties props){
-                if(props.isSetSpcAft()){
-                    CTTextSpacing spc = props.getSpcAft();
-
-                    if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
-                    else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
-                    return true;
-                }
-                return false;
-            }
-        };
-        fetchParagraphProperty(fetcher);
-        return fetcher.getValue();
-    }
-
-    @Override
-    public void setIndentLevel(int level){
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        pr.setLvl(level);
-    }
-
-    @Override
-    public int getIndentLevel() {
-        CTTextParagraphProperties pr = _p.getPPr();
-        return (pr == null || !pr.isSetLvl()) ? 0 : pr.getLvl();
-    }
-
-    /**
-     * Returns whether this paragraph has bullets
-     */
-    public boolean isBullet() {
-        ParagraphPropertyFetcher<Boolean> fetcher = new ParagraphPropertyFetcher<Boolean>(getIndentLevel()){
-            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();
-    }
-
-    /**
-     *
-     * @param flag whether text in this paragraph has bullets
-     */
-    public void setBullet(boolean flag) {
-        if(isBullet() == flag) return;
-
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        if(flag) {
-            pr.addNewBuFont().setTypeface("Arial");
-            pr.addNewBuChar().setChar("\u2022");
-        } else {
-            if (pr.isSetBuFont()) pr.unsetBuFont();
-            if (pr.isSetBuChar()) pr.unsetBuChar();
-            if (pr.isSetBuAutoNum()) pr.unsetBuAutoNum();
-            if (pr.isSetBuBlip()) pr.unsetBuBlip();
-            if (pr.isSetBuClr()) pr.unsetBuClr();
-            if (pr.isSetBuClrTx()) pr.unsetBuClrTx();
-            if (pr.isSetBuFont()) pr.unsetBuFont();
-            if (pr.isSetBuFontTx()) pr.unsetBuFontTx();
-            if (pr.isSetBuSzPct()) pr.unsetBuSzPct();
-            if (pr.isSetBuSzPts()) pr.unsetBuSzPts();
-            if (pr.isSetBuSzTx()) pr.unsetBuSzTx();
-            pr.addNewBuNone();
-        }
-    }
-
-    /**
-     * Specifies that automatic numbered bullet points should be applied to this paragraph
-     *
-     * @param scheme type of auto-numbering
-     * @param startAt the number that will start number for a given sequence of automatically
-    numbered bullets (1-based).
-     */
-    public void setBulletAutoNumber(AutoNumberingScheme scheme, int startAt) {
-        if(startAt < 1) throw new IllegalArgumentException("Start Number must be greater or equal that 1") ;
-        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
-        CTTextAutonumberBullet lst = pr.isSetBuAutoNum() ? pr.getBuAutoNum() : pr.addNewBuAutoNum();
-        lst.setType(STTextAutonumberScheme.Enum.forInt(scheme.ooxmlId));
-        lst.setStartAt(startAt);
-    }
-
-    @Override
-    public String toString(){
-        return "[" + getClass() + "]" + getText();
-    }
-
-
-    /* package */ CTTextParagraphProperties getDefaultMasterStyle(){
-        CTPlaceholder ph = _shape.getCTPlaceholder();
-        String defaultStyleSelector;  
-        switch(ph == null ? -1 : ph.getType().intValue()) {
-            case STPlaceholderType.INT_TITLE:
-            case STPlaceholderType.INT_CTR_TITLE:
-                defaultStyleSelector = "titleStyle";
-                break;
-            case -1: // no placeholder means plain text box
-            case STPlaceholderType.INT_FTR:
-            case STPlaceholderType.INT_SLD_NUM:
-            case STPlaceholderType.INT_DT:
-                defaultStyleSelector = "otherStyle";
-                break;
-            default:
-                defaultStyleSelector = "bodyStyle";
-                break;
-        }
-        int level = getIndentLevel();
-
-        // wind up and find the root master sheet which must be slide master
-        final String nsPML = "http://schemas.openxmlformats.org/presentationml/2006/main";
-        final String nsDML = "http://schemas.openxmlformats.org/drawingml/2006/main";
-        XSLFSheet masterSheet = _shape.getSheet();
-        for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {
-            masterSheet = m;
-            XmlObject xo = masterSheet.getXmlObject();
-            XmlCursor cur = xo.newCursor();
-            try {
-                cur.push();
-                if ((cur.toChild(nsPML, "txStyles") && cur.toChild(nsPML, defaultStyleSelector)) ||
-            		(cur.pop() && cur.toChild(nsPML, "notesStyle"))) {
-                    while (level >= 0) {
-                        cur.push();
-                    	if (cur.toChild(nsDML, "lvl" +(level+1)+ "pPr")) {
-                    		return (CTTextParagraphProperties)cur.getObject();
-                    	}
-                    	cur.pop();
-                    	level--;
-                    }
-                }
-            } finally {
-            	cur.dispose();
-            }
-        }
-        
-        return null;
-    }
-
-    private <T> boolean fetchParagraphProperty(ParagraphPropertyFetcher<T> visitor){
-        boolean ok = false;
-        XSLFTextShape shape = getParentShape();
-        XSLFSheet sheet = shape.getSheet();
-        
-        if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr());
-        if (ok) return true;
-
-        ok = shape.fetchShapeProperty(visitor);
-        if (ok) return true;
-                
-        
-        CTPlaceholder ph = shape.getCTPlaceholder();
-        if(ph == null){
-            // if it is a plain text box then take defaults from presentation.xml
-            @SuppressWarnings("resource")
-            XMLSlideShow ppt = sheet.getSlideShow();
-            CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel());
-            if (themeProps != null) ok = visitor.fetch(themeProps);
-        }
-        if (ok) return true;
-
-        // defaults for placeholders are defined in the slide master
-        CTTextParagraphProperties defaultProps = getDefaultMasterStyle();
-        // TODO: determine master shape
-        if(defaultProps != null) ok = visitor.fetch(defaultProps);
-        if (ok) return true;
-
-        return false;
-    }
-
-    void copy(XSLFTextParagraph other){
-        if (other == this) return;
-        
-        CTTextParagraph thisP = getXmlObject();
-        CTTextParagraph otherP = other.getXmlObject();
-        
-        if (thisP.isSetPPr()) thisP.unsetPPr();
-        if (thisP.isSetEndParaRPr()) thisP.unsetEndParaRPr();
-        
-        _runs.clear();
-        for (int i=thisP.sizeOfBrArray(); i>0; i--) {
-            thisP.removeBr(i-1);
-        }
-        for (int i=thisP.sizeOfRArray(); i>0; i--) {
-            thisP.removeR(i-1);
-        }
-        for (int i=thisP.sizeOfFldArray(); i>0; i--) {
-            thisP.removeFld(i-1);
-        }
-
-        XmlCursor thisC = thisP.newCursor();
-        thisC.toEndToken();
-        XmlCursor otherC = otherP.newCursor();
-        otherC.copyXmlContents(thisC);
-        otherC.dispose();
-        thisC.dispose();
-        
-        List<XSLFTextRun> otherRs = other.getTextRuns();
-        int i=0;
-        for(CTRegularTextRun rtr : thisP.getRArray()) {
-            XSLFTextRun run = newTextRun(rtr);
-            run.copy(otherRs.get(i++));
-            _runs.add(run);
-        }
-        
-        
-        // set properties again, in case we are based on a different
-        // template
-        TextAlign srcAlign = other.getTextAlign();
-        if(srcAlign != getTextAlign()){
-            setTextAlign(srcAlign);
-        }
-
-        boolean isBullet = other.isBullet();
-        if(isBullet != isBullet()){
-            setBullet(isBullet);
-            if(isBullet) {
-                String buFont = other.getBulletFont();
-                if(buFont != null && !buFont.equals(getBulletFont())){
-                    setBulletFont(buFont);
-                }
-                String buChar = other.getBulletCharacter();
-                if(buChar != null && !buChar.equals(getBulletCharacter())){
-                    setBulletCharacter(buChar);
-                }
-                PaintStyle buColor = other.getBulletFontColor();
-                if(buColor != null && !buColor.equals(getBulletFontColor())){
-                    setBulletFontColor(buColor);
-                }
-                Double buSize = other.getBulletFontSize();
-                if(!doubleEquals(buSize, getBulletFontSize())){
-                    setBulletFontSize(buSize);
-                }
-            }
-        }
-
-        Double leftMargin = other.getLeftMargin();
-        if (!doubleEquals(leftMargin, getLeftMargin())){
-            setLeftMargin(leftMargin);
-        }
-
-        Double indent = other.getIndent();
-        if (!doubleEquals(indent, getIndent())) {
-            setIndent(indent);
-        }
-
-        Double spaceAfter = other.getSpaceAfter();
-        if (!doubleEquals(spaceAfter, getSpaceAfter())) {
-            setSpaceAfter(spaceAfter);
-        }
-        
-        Double spaceBefore = other.getSpaceBefore();
-        if (!doubleEquals(spaceBefore, getSpaceBefore())) {
-            setSpaceBefore(spaceBefore);
-        }
-        
-        Double lineSpacing = other.getLineSpacing();
-        if (!doubleEquals(lineSpacing, getLineSpacing())) {
-            setLineSpacing(lineSpacing);
-        }
-    }
-
-    private static boolean doubleEquals(Double d1, Double d2) {
-        return (d1 == d2 || (d1 != null && d1.equals(d2)));
-    }
-    
-    @Override
-    public Double getDefaultFontSize() {
-        CTTextCharacterProperties endPr = _p.getEndParaRPr();
-        if (endPr == null || !endPr.isSetSz()) {
-            endPr = getDefaultMasterStyle().getDefRPr();
-        }
-        return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.);
-    }
-
-    @Override
-    public String getDefaultFontFamily() {
-        return (_runs.isEmpty() ? "Arial" : _runs.get(0).getFontFamily());
-    }
-
-    @Override
-    public BulletStyle getBulletStyle() {
-        if (!isBullet()) return null;
-        return new BulletStyle(){
-            @Override
-            public String getBulletCharacter() {
-                return XSLFTextParagraph.this.getBulletCharacter();
-            }
-
-            @Override
-            public String getBulletFont() {
-                return XSLFTextParagraph.this.getBulletFont();
-            }
-
-            @Override
-            public Double getBulletFontSize() {
-                return XSLFTextParagraph.this.getBulletFontSize();
-            }
-
-            @Override
-            public PaintStyle getBulletFontColor() {
-                return XSLFTextParagraph.this.getBulletFontColor();
-            }
-            
-            @Override
-            public void setBulletFontColor(Color color) {
-                setBulletFontColor(DrawPaint.createSolidPaint(color));
-            }
-
-            @Override
-            public void setBulletFontColor(PaintStyle color) {
-                XSLFTextParagraph.this.setBulletFontColor(color);
-            }
-            
-            @Override
-            public AutoNumberingScheme getAutoNumberingScheme() {
-                return XSLFTextParagraph.this.getAutoNumberingScheme();
-            }
-
-            @Override
-            public Integer getAutoNumberingStartAt() {
-                return XSLFTextParagraph.this.getAutoNumberingStartAt();
-            }
-
-        };
-    }
-
-    @Override
-    public void setBulletStyle(Object... styles) {
-        if (styles.length == 0) {
-            setBullet(false);
-        } else {
-            setBullet(true);
-            for (Object ostyle : styles) {
-                if (ostyle instanceof Number) {
-                    setBulletFontSize(((Number)ostyle).doubleValue());
-                } else if (ostyle instanceof Color) {
-                    setBulletFontColor((Color)ostyle);
-                } else if (ostyle instanceof Character) {
-                    setBulletCharacter(ostyle.toString());
-                } else if (ostyle instanceof String) {
-                    setBulletFont((String)ostyle);
-                } else if (ostyle instanceof AutoNumberingScheme) {
-                    setBulletAutoNumber((AutoNumberingScheme)ostyle, 0);
-                }
-            }
-        }
-    }
-    
-    /**
-     * Helper method for appending text and keeping paragraph and character properties.
-     * The character properties are moved to the end paragraph marker
-     */
-    /* package */ void clearButKeepProperties() {
-        CTTextParagraph thisP = getXmlObject();
-        for (int i=thisP.sizeOfBrArray(); i>0; i--) {
-            thisP.removeBr(i-1);
-        }
-        for (int i=thisP.sizeOfFldArray(); i>0; i--) {
-            thisP.removeFld(i-1);
-        }
-        if (!_runs.isEmpty()) {
-            int size = _runs.size();
-            XSLFTextRun lastRun = _runs.get(size-1);
-            CTTextCharacterProperties cpOther = lastRun.getRPr(false);
-            if (cpOther != null) {
-                if (thisP.isSetEndParaRPr()) {
-                    thisP.unsetEndParaRPr();
-                }
-                CTTextCharacterProperties cp = thisP.addNewEndParaRPr();
-                cp.set(cpOther);
-            }
-            for (int i=size; i>0; i--) {
-                thisP.removeR(i-1);
-            }
-            _runs.clear();
-        }
-    }
-
-    @Override
-    public boolean isHeaderOrFooter() {
-        CTPlaceholder ph = _shape.getCTPlaceholder();
-        int phId = (ph == null ? -1 : ph.getType().intValue());
-        switch (phId) {
-            case STPlaceholderType.INT_SLD_NUM:
-            case STPlaceholderType.INT_DT:
-            case STPlaceholderType.INT_FTR:
-            case STPlaceholderType.INT_HDR:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * Helper method to allow subclasses to provide their own text run
-     *
-     * @param r the xml reference
-     * 
-     * @return a new text paragraph
-     * 
-     * @since POI 3.15-beta2
-     */
-    protected XSLFTextRun newTextRun(CTRegularTextRun r) {
-        return new XSLFTextRun(r, this);
-    }
-}
\ No newline at end of file
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+package org.apache.poi.xslf.usermodel;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.poi.sl.draw.DrawPaint;
+import org.apache.poi.sl.usermodel.AutoNumberingScheme;
+import org.apache.poi.sl.usermodel.PaintStyle;
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.sl.usermodel.TextParagraph;
+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.xmlbeans.XmlCursor;
+import org.apache.xmlbeans.XmlObject;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextAutonumberBullet;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePercent;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBulletSizePoint;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharBullet;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextField;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextLineBreak;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextSpacing;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStop;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextTabStopList;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAutonumberScheme;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextFontAlignType;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
+import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
+
+/**
+ * Represents a paragraph of text within the containing text body.
+ * The paragraph is the highest level text separation mechanism.
+ *
+ * @since POI-3.8
+ */
+@Beta
+public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagraph,XSLFTextRun> {
+    private final CTTextParagraph _p;
+    private final List<XSLFTextRun> _runs;
+    private final XSLFTextShape _shape;
+
+    XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
+        _p = p;
+        _runs = new ArrayList<XSLFTextRun>();
+        _shape = shape;
+
+        for(XmlObject ch : _p.selectPath("*")){
+            if(ch instanceof CTRegularTextRun){
+                CTRegularTextRun r = (CTRegularTextRun)ch;
+                _runs.add(newTextRun(r));
+            } else if (ch instanceof CTTextLineBreak){
+                CTTextLineBreak br = (CTTextLineBreak)ch;
+                CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
+                r.setRPr(br.getRPr());
+                r.setT("\n");
+                _runs.add(newTextRun(r));
+            } else if (ch instanceof CTTextField){
+                CTTextField f = (CTTextField)ch;
+                CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
+                r.setRPr(f.getRPr());
+                r.setT(f.getT());
+                _runs.add(newTextRun(r));
+            }
+        }
+    }
+
+    public String getText(){
+        StringBuilder out = new StringBuilder();
+        for (XSLFTextRun r : _runs) {
+            out.append(r.getRawText());
+        }
+        return out.toString();
+    }
+
+    String getRenderableText(){
+        StringBuilder out = new StringBuilder();
+        for (XSLFTextRun r : _runs) {
+            out.append(r.getRenderableText());
+        }
+        return out.toString();
+    }
+
+    @Internal
+    public CTTextParagraph getXmlObject(){
+        return _p;
+    }
+
+    public XSLFTextShape getParentShape() {
+        return _shape;
+
+    }
+
+    @Override
+    public List<XSLFTextRun> getTextRuns(){
+        return _runs;
+    }
+
+    public Iterator<XSLFTextRun> iterator(){
+        return _runs.iterator();
+    }
+
+    /**
+     * Add a new run of text
+     *
+     * @return a new run of text
+     */
+    public XSLFTextRun addNewTextRun(){
+        CTRegularTextRun r = _p.addNewR();
+        CTTextCharacterProperties rPr = r.addNewRPr();
+        rPr.setLang("en-US");
+        XSLFTextRun run = newTextRun(r);
+        _runs.add(run);
+        return run;
+    }
+
+    /**
+     * Insert a line break
+     *
+     * @return text run representing this line break ('\n')
+     */
+    public XSLFTextRun addLineBreak(){
+        CTTextLineBreak br = _p.addNewBr();
+        CTTextCharacterProperties brProps = br.addNewRPr();
+        if(_runs.size() > 0){
+            // by default line break has the font size of the last text run
+            CTTextCharacterProperties prevRun = _runs.get(_runs.size() - 1).getRPr(true);
+            brProps.set(prevRun);
+        }
+        CTRegularTextRun r = CTRegularTextRun.Factory.newInstance();
+        r.setRPr(brProps);
+        r.setT("\n");
+        XSLFTextRun run = new XSLFLineBreak(r, this, brProps);
+        _runs.add(run);
+        return run;
+    }
+
+    @Override
+    public TextAlign getTextAlign(){
+        ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetAlgn()){
+                    TextAlign val = TextAlign.values()[props.getAlgn().intValue() - 1];
+                    setValue(val);
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    @Override
+    public void setTextAlign(TextAlign align) {
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        if(align == null) {
+            if(pr.isSetAlgn()) pr.unsetAlgn();
+        } else {
+            pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1));
+        }
+    }
+
+    @Override
+    public FontAlign getFontAlign(){
+        ParagraphPropertyFetcher<FontAlign> fetcher = new ParagraphPropertyFetcher<FontAlign>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetFontAlgn()){
+                    FontAlign val = FontAlign.values()[props.getFontAlgn().intValue() - 1];
+                    setValue(val);
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    /**
+     * Specifies the font alignment that is to be applied to the paragraph.
+     * Possible values for this include auto, top, center, baseline and bottom.
+     * see {@link org.apache.poi.sl.usermodel.TextParagraph.FontAlign}.
+     *
+     * @param align font align
+     */
+    public void setFontAlign(FontAlign align){
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        if(align == null) {
+            if(pr.isSetFontAlgn()) pr.unsetFontAlgn();
+        } else {
+            pr.setFontAlgn(STTextFontAlignType.Enum.forInt(align.ordinal() + 1));
+        }
+    }
+
+    
+
+    /**
+     * @return the font to be used on bullet characters within a given paragraph
+     */
+    public String getBulletFont(){
+        ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetBuFont()){
+                    setValue(props.getBuFont().getTypeface());
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    public void setBulletFont(String typeface){
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        CTTextFont font = pr.isSetBuFont() ? pr.getBuFont() : pr.addNewBuFont();
+        font.setTypeface(typeface);
+    }
+
+    /**
+     * @return the character to be used in place of the standard bullet point
+     */
+    public String getBulletCharacter(){
+        ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetBuChar()){
+                    setValue(props.getBuChar().getChar());
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    public void setBulletCharacter(String str){
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        CTTextCharBullet c = pr.isSetBuChar() ? pr.getBuChar() : pr.addNewBuChar();
+        c.setChar(str);
+    }
+
+    /**
+     *
+     * @return the color of bullet characters within a given paragraph.
+     * A <code>null</code> value means to use the text font color.
+     */
+    public PaintStyle getBulletFontColor(){
+        final XSLFTheme theme = getParentShape().getSheet().getTheme();
+        ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetBuClr()){
+                    XSLFColor c = new XSLFColor(props.getBuClr(), theme, null);
+                    setValue(c.getColor());
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        Color col = fetcher.getValue();
+        return (col == null) ? null : DrawPaint.createSolidPaint(col);
+    }
+
+    public void setBulletFontColor(Color color) {
+        setBulletFontColor(DrawPaint.createSolidPaint(color));
+    }
+    
+    
+    /**
+     * Set the color to be used on bullet characters within a given paragraph.
+     *
+     * @param color the bullet color
+     */
+    public void setBulletFontColor(PaintStyle color) {
+        if (!(color instanceof SolidPaint)) {
+            throw new IllegalArgumentException("Currently XSLF only supports SolidPaint");
+        }
+
+        // TODO: implement setting bullet color to null
+        SolidPaint sp = (SolidPaint)color;
+        Color col = DrawPaint.applyColorTransform(sp.getSolidColor());
+        
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr();
+        CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr();
+        clr.setVal(new byte[]{(byte) col.getRed(), (byte) col.getGreen(), (byte) col.getBlue()});
+    }
+
+    /**
+     * Returns 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:
+     * <p>
+     * If bulletSize >= 0, then bulletSize is a percentage of the font size.
+     * If bulletSize < 0, then it specifies the size in points
+     * </p>
+     *
+     * @return the bullet size
+     */
+    public Double getBulletFontSize(){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            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();
+    }
+
+    /**
+     * 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:
+     * <p>
+     * If bulletSize >= 0, then bulletSize is a percentage of the font size.
+     * If bulletSize < 0, then it specifies the size in points
+     * </p>
+     */
+    public void setBulletFontSize(double bulletSize){
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+
+        if(bulletSize >= 0) {
+            CTTextBulletSizePercent pt = pr.isSetBuSzPct() ? pr.getBuSzPct() : pr.addNewBuSzPct();
+            pt.setVal((int)(bulletSize*1000));
+            if(pr.isSetBuSzPts()) pr.unsetBuSzPts();
+        } else {
+            CTTextBulletSizePoint pt = pr.isSetBuSzPts() ? pr.getBuSzPts() : pr.addNewBuSzPts();
+            pt.setVal((int)(-bulletSize*100));
+            if(pr.isSetBuSzPct()) pr.unsetBuSzPct();
+        }
+   }
+
+    /**
+     * @return the auto numbering scheme, or null if not defined
+     */
+    public AutoNumberingScheme getAutoNumberingScheme() {
+        ParagraphPropertyFetcher<AutoNumberingScheme> fetcher = new ParagraphPropertyFetcher<AutoNumberingScheme>(getIndentLevel()) {
+            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;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    /**
+     * @return the auto numbering starting number, or null if not defined
+     */
+    public Integer getAutoNumberingStartAt() {
+        ParagraphPropertyFetcher<Integer> fetcher = new ParagraphPropertyFetcher<Integer>(getIndentLevel()) {
+            public boolean fetch(CTTextParagraphProperties props) {
+                if (props.isSetBuAutoNum()) {
+                    if (props.getBuAutoNum().isSetStartAt()) {
+                        setValue(props.getBuAutoNum().getStartAt());
+                        return true;
+                    }
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+    
+    
+    @Override
+    public void setIndent(Double indent){
+        if ((indent == null) && !_p.isSetPPr()) return;
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        if(indent == null) {
+            if(pr.isSetIndent()) pr.unsetIndent();
+        } else {
+            pr.setIndent(Units.toEMU(indent));
+        }
+    }
+
+    @Override
+    public Double getIndent() {
+
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetIndent()){
+                    setValue(Units.toPoints(props.getIndent()));
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+
+        return fetcher.getValue();
+    }
+
+    @Override
+    public void setLeftMargin(Double leftMargin){
+        if (leftMargin == null && !_p.isSetPPr()) return;
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        if (leftMargin == null) {
+            if(pr.isSetMarL()) pr.unsetMarL();
+        } else {
+            pr.setMarL(Units.toEMU(leftMargin));
+        }
+
+    }
+
+    /**
+     * @return the left margin (in points) of the paragraph, null if unset
+     */
+    @Override
+    public Double getLeftMargin(){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetMarL()){
+                    double val = Units.toPoints(props.getMarL());
+                    setValue(val);
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        // if the marL attribute is omitted, then a value of 347663 is implied
+        return fetcher.getValue();
+    }
+
+    @Override
+    public void setRightMargin(Double rightMargin){
+        if (rightMargin == null && !_p.isSetPPr()) return;
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        if(rightMargin == null) {
+            if(pr.isSetMarR()) pr.unsetMarR();
+        } else {
+            pr.setMarR(Units.toEMU(rightMargin));
+        }
+    }
+
+    /**
+     *
+     * @return the right margin of the paragraph, null if unset
+     */
+    @Override
+    public Double getRightMargin(){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetMarR()){
+                    double val = Units.toPoints(props.getMarR());
+                    setValue(val);
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    @Override
+    public Double getDefaultTabSize(){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetDefTabSz()){
+                    double val = Units.toPoints(props.getDefTabSz());
+                    setValue(val);
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    public double getTabStop(final int idx){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            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;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue() == null ? 0. : fetcher.getValue();
+    }
+
+    public void addTabStop(double value){
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        CTTextTabStopList tabStops = pr.isSetTabLst() ? pr.getTabLst() : pr.addNewTabLst();
+        tabStops.addNewTab().setPos(Units.toEMU(value));
+    }
+
+    @Override
+    public void setLineSpacing(Double lineSpacing){
+        if (lineSpacing == null && !_p.isSetPPr()) return;
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        if(lineSpacing == null) {
+            if (pr.isSetLnSpc()) pr.unsetLnSpc();
+        } else {
+            CTTextSpacing spc = (pr.isSetLnSpc()) ? pr.getLnSpc() : pr.addNewLnSpc();
+            if (lineSpacing >= 0) {
+                (spc.isSetSpcPct() ? spc.getSpcPct() : spc.addNewSpcPct()).setVal((int)(lineSpacing*1000));
+                if (spc.isSetSpcPts()) spc.unsetSpcPts();
+            } else {
+                (spc.isSetSpcPts() ? spc.getSpcPts() : spc.addNewSpcPts()).setVal((int)(-lineSpacing*100));
+                if (spc.isSetSpcPct()) spc.unsetSpcPct();
+            }
+        }
+    }
+
+    @Override
+    public Double getLineSpacing(){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetLnSpc()){
+                    CTTextSpacing spc = props.getLnSpc();
+
+                    if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
+                    else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+
+        Double lnSpc = fetcher.getValue();
+        if (lnSpc != null && lnSpc > 0) {
+            // check if the percentage value is scaled
+            CTTextNormalAutofit normAutofit = getParentShape().getTextBodyPr().getNormAutofit();
+            if(normAutofit != null) {
+                double scale = 1 - (double)normAutofit.getLnSpcReduction() / 100000;
+                lnSpc *= scale;
+            }
+        }
+        
+        return lnSpc;
+    }
+
+    @Override
+    public void setSpaceBefore(Double spaceBefore){
+        if (spaceBefore == null && !_p.isSetPPr()) {
+            return;
+        }
+
+        // unset the space before on null input
+        if (spaceBefore == null) {
+            if(_p.getPPr().isSetSpcBef()) {
+                _p.getPPr().unsetSpcBef();
+            }
+            return;
+        }
+
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
+
+        if(spaceBefore >= 0) {
+            spc.addNewSpcPct().setVal((int)(spaceBefore*1000));
+        } else {
+            spc.addNewSpcPts().setVal((int)(-spaceBefore*100));
+        }
+        pr.setSpcBef(spc);
+    }
+
+    @Override
+    public Double getSpaceBefore(){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetSpcBef()){
+                    CTTextSpacing spc = props.getSpcBef();
+
+                    if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
+                    else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+
+        return fetcher.getValue();
+    }
+
+    @Override
+    public void setSpaceAfter(Double spaceAfter){
+        if (spaceAfter == null && !_p.isSetPPr()) {
+            return;
+        }
+
+        // unset the space before on null input
+        if (spaceAfter == null) {
+            if(_p.getPPr().isSetSpcAft()) {
+                _p.getPPr().unsetSpcAft();
+            }
+            return;
+        }
+
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
+
+        if(spaceAfter >= 0) {
+            spc.addNewSpcPct().setVal((int)(spaceAfter*1000));
+        } else {
+            spc.addNewSpcPts().setVal((int)(-spaceAfter*100));
+        }
+        pr.setSpcAft(spc);
+    }
+
+    @Override
+    public Double getSpaceAfter(){
+        ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getIndentLevel()){
+            public boolean fetch(CTTextParagraphProperties props){
+                if(props.isSetSpcAft()){
+                    CTTextSpacing spc = props.getSpcAft();
+
+                    if(spc.isSetSpcPct()) setValue( spc.getSpcPct().getVal()*0.001 );
+                    else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 );
+                    return true;
+                }
+                return false;
+            }
+        };
+        fetchParagraphProperty(fetcher);
+        return fetcher.getValue();
+    }
+
+    @Override
+    public void setIndentLevel(int level){
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        pr.setLvl(level);
+    }
+
+    @Override
+    public int getIndentLevel() {
+        CTTextParagraphProperties pr = _p.getPPr();
+        return (pr == null || !pr.isSetLvl()) ? 0 : pr.getLvl();
+    }
+
+    /**
+     * Returns whether this paragraph has bullets
+     */
+    public boolean isBullet() {
+        ParagraphPropertyFetcher<Boolean> fetcher = new ParagraphPropertyFetcher<Boolean>(getIndentLevel()){
+            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();
+    }
+
+    /**
+     *
+     * @param flag whether text in this paragraph has bullets
+     */
+    public void setBullet(boolean flag) {
+        if(isBullet() == flag) return;
+
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        if(flag) {
+            pr.addNewBuFont().setTypeface("Arial");
+            pr.addNewBuChar().setChar("\u2022");
+        } else {
+            if (pr.isSetBuFont()) pr.unsetBuFont();
+            if (pr.isSetBuChar()) pr.unsetBuChar();
+            if (pr.isSetBuAutoNum()) pr.unsetBuAutoNum();
+            if (pr.isSetBuBlip()) pr.unsetBuBlip();
+            if (pr.isSetBuClr()) pr.unsetBuClr();
+            if (pr.isSetBuClrTx()) pr.unsetBuClrTx();
+            if (pr.isSetBuFont()) pr.unsetBuFont();
+            if (pr.isSetBuFontTx()) pr.unsetBuFontTx();
+            if (pr.isSetBuSzPct()) pr.unsetBuSzPct();
+            if (pr.isSetBuSzPts()) pr.unsetBuSzPts();
+            if (pr.isSetBuSzTx()) pr.unsetBuSzTx();
+            pr.addNewBuNone();
+        }
+    }
+
+    /**
+     * Specifies that automatic numbered bullet points should be applied to this paragraph
+     *
+     * @param scheme type of auto-numbering
+     * @param startAt the number that will start number for a given sequence of automatically
+    numbered bullets (1-based).
+     */
+    public void setBulletAutoNumber(AutoNumberingScheme scheme, int startAt) {
+        if(startAt < 1) throw new IllegalArgumentException("Start Number must be greater or equal that 1") ;
+        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
+        CTTextAutonumberBullet lst = pr.isSetBuAutoNum() ? pr.getBuAutoNum() : pr.addNewBuAutoNum();
+        lst.setType(STTextAutonumberScheme.Enum.forInt(scheme.ooxmlId));
+        lst.setStartAt(startAt);
+    }
+
+    @Override
+    public String toString(){
+        return "[" + getClass() + "]" + getText();
+    }
+
+
+    /**
+     * @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
+     */
+    /* package */ CTTextParagraphProperties getDefaultMasterStyle(){
+        CTPlaceholder ph = _shape.getCTPlaceholder();
+        String defaultStyleSelector;  
+        switch(ph == null ? -1 : ph.getType().intValue()) {
+            case STPlaceholderType.INT_TITLE:
+            case STPlaceholderType.INT_CTR_TITLE:
+                defaultStyleSelector = "titleStyle";
+                break;
+            case -1: // no placeholder means plain text box
+            case STPlaceholderType.INT_FTR:
+            case STPlaceholderType.INT_SLD_NUM:
+            case STPlaceholderType.INT_DT:
+                defaultStyleSelector = "otherStyle";
+                break;
+            default:
+                defaultStyleSelector = "bodyStyle";
+                break;
+        }
+        int level = getIndentLevel();
+
+        // wind up and find the root master sheet which must be slide master
+        final String nsPML = "http://schemas.openxmlformats.org/presentationml/2006/main";
+        final String nsDML = "http://schemas.openxmlformats.org/drawingml/2006/main";
+        XSLFSheet masterSheet = _shape.getSheet();
+        for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {
+            masterSheet = m;
+            XmlObject xo = masterSheet.getXmlObject();
+            XmlCursor cur = xo.newCursor();
+            try {
+                cur.push();
+                if ((cur.toChild(nsPML, "txStyles") && cur.toChild(nsPML, defaultStyleSelector)) ||
+            		(cur.pop() && cur.toChild(nsPML, "notesStyle"))) {
+                    while (level >= 0) {
+                        cur.push();
+                    	if (cur.toChild(nsDML, "lvl" +(level+1)+ "pPr")) {
+                    		return (CTTextParagraphProperties)cur.getObject();
+                    	}
+                    	cur.pop();
+                    	level--;
+                    }
+                }
+            } finally {
+            	cur.dispose();
+            }
+        }
+        
+        return null;
+    }
+
+    private <T> boolean fetchParagraphProperty(ParagraphPropertyFetcher<T> visitor){
+        boolean ok = false;
+        XSLFTextShape shape = getParentShape();
+        XSLFSheet sheet = shape.getSheet();
+        
+        if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr());
+        if (ok) return true;
+
+        ok = shape.fetchShapeProperty(visitor);
+        if (ok) return true;
+                
+        
+        CTPlaceholder ph = shape.getCTPlaceholder();
+        if(ph == null){
+            // if it is a plain text box then take defaults from presentation.xml
+            @SuppressWarnings("resource")
+            XMLSlideShow ppt = sheet.getSlideShow();
+            CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel());
+            if (themeProps != null) ok = visitor.fetch(themeProps);
+        }
+        if (ok) return true;
+
+        // defaults for placeholders are defined in the slide master
+        CTTextParagraphProperties defaultProps = getDefaultMasterStyle();
+        // TODO: determine master shape
+        if(defaultProps != null) ok = visitor.fetch(defaultProps);
+        if (ok) return true;
+
+        return false;
+    }
+
+    void copy(XSLFTextParagraph other){
+        if (other == this) return;
+        
+        CTTextParagraph thisP = getXmlObject();
+        CTTextParagraph otherP = other.getXmlObject();
+        
+        if (thisP.isSetPPr()) thisP.unsetPPr();
+        if (thisP.isSetEndParaRPr()) thisP.unsetEndParaRPr();
+        
+        _runs.clear();
+        for (int i=thisP.sizeOfBrArray(); i>0; i--) {
+            thisP.removeBr(i-1);
+        }
+        for (int i=thisP.sizeOfRArray(); i>0; i--) {
+            thisP.removeR(i-1);
+        }
+        for (int i=thisP.sizeOfFldArray(); i>0; i--) {
+            thisP.removeFld(i-1);
+        }
+
+        XmlCursor thisC = thisP.newCursor();
+        thisC.toEndToken();
+        XmlCursor otherC = otherP.newCursor();
+        otherC.copyXmlContents(thisC);
+        otherC.dispose();
+        thisC.dispose();
+        
+        List<XSLFTextRun> otherRs = other.getTextRuns();
+        int i=0;
+        for(CTRegularTextRun rtr : thisP.getRArray()) {
+            XSLFTextRun run = newTextRun(rtr);
+            run.copy(otherRs.get(i++));
+            _runs.add(run);
+        }
+        
+        
+        // set properties again, in case we are based on a different
+        // template
+        TextAlign srcAlign = other.getTextAlign();
+        if(srcAlign != getTextAlign()){
+            setTextAlign(srcAlign);
+        }
+
+        boolean isBullet = other.isBullet();
+        if(isBullet != isBullet()){
+            setBullet(isBullet);
+            if(isBullet) {
+                String buFont = other.getBulletFont();
+                if(buFont != null && !buFont.equals(getBulletFont())){
+                    setBulletFont(buFont);
+                }
+                String buChar = other.getBulletCharacter();
+                if(buChar != null && !buChar.equals(getBulletCharacter())){
+                    setBulletCharacter(buChar);
+                }
+                PaintStyle buColor = other.getBulletFontColor();
+                if(buColor != null && !buColor.equals(getBulletFontColor())){
+                    setBulletFontColor(buColor);
+                }
+                Double buSize = other.getBulletFontSize();
+                if(!doubleEquals(buSize, getBulletFontSize())){
+                    setBulletFontSize(buSize);
+                }
+            }
+        }
+
+        Double leftMargin = other.getLeftMargin();
+        if (!doubleEquals(leftMargin, getLeftMargin())){
+            setLeftMargin(leftMargin);
+        }
+
+        Double indent = other.getIndent();
+        if (!doubleEquals(indent, getIndent())) {
+            setIndent(indent);
+        }
+
+        Double spaceAfter = other.getSpaceAfter();
+        if (!doubleEquals(spaceAfter, getSpaceAfter())) {
+            setSpaceAfter(spaceAfter);
+        }
+        
+        Double spaceBefore = other.getSpaceBefore();
+        if (!doubleEquals(spaceBefore, getSpaceBefore())) {
+            setSpaceBefore(spaceBefore);
+        }
+        
+        Double lineSpacing = other.getLineSpacing();
+        if (!doubleEquals(lineSpacing, getLineSpacing())) {
+            setLineSpacing(lineSpacing);
+        }
+    }
+
+    private static boolean doubleEquals(Double d1, Double d2) {
+        return (d1 == d2 || (d1 != null && d1.equals(d2)));
+    }
+    
+    @Override
+    public Double getDefaultFontSize() {
+        CTTextCharacterProperties endPr = _p.getEndParaRPr();
+        if (endPr == null || !endPr.isSetSz()) {
+            // inherit the font size from the master style
+            CTTextParagraphProperties masterStyle = getDefaultMasterStyle();
+            if (masterStyle != null) {
+                endPr = masterStyle.getDefRPr();
+            }
+        }
+        return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.);
+    }
+
+    @Override
+    public String getDefaultFontFamily() {
+        return (_runs.isEmpty() ? "Arial" : _runs.get(0).getFontFamily());
+    }
+
+    @Override
+    public BulletStyle getBulletStyle() {
+        if (!isBullet()) return null;
+        return new BulletStyle(){
+            @Override
+            public String getBulletCharacter() {
+                return XSLFTextParagraph.this.getBulletCharacter();
+            }
+
+            @Override
+            public String getBulletFont() {
+                return XSLFTextParagraph.this.getBulletFont();
+            }
+
+            @Override
+            public Double getBulletFontSize() {
+                return XSLFTextParagraph.this.getBulletFontSize();
+            }
+
+            @Override
+            public PaintStyle getBulletFontColor() {
+                return XSLFTextParagraph.this.getBulletFontColor();
+            }
+            
+            @Override
+            public void setBulletFontColor(Color color) {
+                setBulletFontColor(DrawPaint.createSolidPaint(color));
+            }
+
+            @Override
+            public void setBulletFontColor(PaintStyle color) {
+                XSLFTextParagraph.this.setBulletFontColor(color);
+            }
+            
+            @Override
+            public AutoNumberingScheme getAutoNumberingScheme() {
+                return XSLFTextParagraph.this.getAutoNumberingScheme();
+            }
+
+            @Override
+            public Integer getAutoNumberingStartAt() {
+                return XSLFTextParagraph.this.getAutoNumberingStartAt();
+            }
+
+        };
+    }
+
+    @Override
+    public void setBulletStyle(Object... styles) {
+        if (styles.length == 0) {
+            setBullet(false);
+        } else {
+            setBullet(true);
+            for (Object ostyle : styles) {
+                if (ostyle instanceof Number) {
+                    setBulletFontSize(((Number)ostyle).doubleValue());
+                } else if (ostyle instanceof Color) {
+                    setBulletFontColor((Color)ostyle);
+                } else if (ostyle instanceof Character) {
+                    setBulletCharacter(ostyle.toString());
+                } else if (ostyle instanceof String) {
+                    setBulletFont((String)ostyle);
+                } else if (ostyle instanceof AutoNumberingScheme) {
+                    setBulletAutoNumber((AutoNumberingScheme)ostyle, 0);
+                }
+            }
+        }
+    }
+    
+    /**
+     * Helper method for appending text and keeping paragraph and character properties.
+     * The character properties are moved to the end paragraph marker
+     */
+    /* package */ void clearButKeepProperties() {
+        CTTextParagraph thisP = getXmlObject();
+        for (int i=thisP.sizeOfBrArray(); i>0; i--) {
+            thisP.removeBr(i-1);
+        }
+        for (int i=thisP.sizeOfFldArray(); i>0; i--) {
+            thisP.removeFld(i-1);
+        }
+        if (!_runs.isEmpty()) {
+            int size = _runs.size();
+            XSLFTextRun lastRun = _runs.get(size-1);
+            CTTextCharacterProperties cpOther = lastRun.getRPr(false);
+            if (cpOther != null) {
+                if (thisP.isSetEndParaRPr()) {
+                    thisP.unsetEndParaRPr();
+                }
+                CTTextCharacterProperties cp = thisP.addNewEndParaRPr();
+                cp.set(cpOther);
+            }
+            for (int i=size; i>0; i--) {
+                thisP.removeR(i-1);
+            }
+            _runs.clear();
+        }
+    }
+
+    @Override
+    public boolean isHeaderOrFooter() {
+        CTPlaceholder ph = _shape.getCTPlaceholder();
+        int phId = (ph == null ? -1 : ph.getType().intValue());
+        switch (phId) {
+            case STPlaceholderType.INT_SLD_NUM:
+            case STPlaceholderType.INT_DT:
+            case STPlaceholderType.INT_FTR:
+            case STPlaceholderType.INT_HDR:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Helper method to allow subclasses to provide their own text run
+     *
+     * @param r the xml reference
+     * 
+     * @return a new text paragraph
+     * 
+     * @since POI 3.15-beta2
+     */
+    protected XSLFTextRun newTextRun(CTRegularTextRun r) {
+        return new XSLFTextRun(r, this);
+    }
+}

Propchange: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFSheetAutoSizeColumn.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFSheetAutoSizeColumn.java?rev=1756967&r1=1756966&r2=1756967&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFSheetAutoSizeColumn.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFSheetAutoSizeColumn.java Fri Aug 19 20:57:56 2016
@@ -63,7 +63,7 @@ public class TestSXSSFSheetAutoSizeColum
     //  longCellValue ends up with approx. column width 10_000 (on my machine)
     //  so shortCellValue can be expected to be < 5000 for all fonts
     //  and longCellValue can be expected to be > 5000 for all fonts
-    private static final int COLUMN_WIDTH_THRESHOLD_BETWEEN_SHORT_AND_LONG = 5000;
+    private static final int COLUMN_WIDTH_THRESHOLD_BETWEEN_SHORT_AND_LONG = 4000;
     private static final int MAX_COLUMN_WIDTH = 255*256;
     
     private static final SortedSet<Integer> columns;

Modified: poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java?rev=1756967&r1=1756966&r2=1756967&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java (original)
+++ poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java Fri Aug 19 20:57:56 2016
@@ -32,9 +32,9 @@ import org.apache.poi.poifs.filesystem.*
  * @author Nick Burch
  */
 public final class PowerPointExtractor extends POIOLE2TextExtractor {
-   private HSLFSlideShowImpl _hslfshow;
-   private HSLFSlideShow _show;
-   private List<HSLFSlide> _slides;
+   private final HSLFSlideShowImpl _hslfshow;
+   private final HSLFSlideShow _show;
+   private final List<HSLFSlide> _slides;
 
    private boolean _slidesByDefault = true;
    private boolean _notesByDefault = false;
@@ -240,9 +240,9 @@ public final class PowerPointExtractor e
                 }
                 
                 // Slide header, if set
-				ret.append(headerText);
+                ret.append(headerText);
 
-				// Slide text
+                // Slide text
                 textRunsToText(ret, slide.getTextParagraphs());
 
                 // Table text
@@ -256,14 +256,13 @@ public final class PowerPointExtractor e
 
 				// Comments, if requested and present
 				if (getCommentText) {
-					Comment[] comments = slide.getComments();
-					for (int j = 0; j < comments.length; j++) {
-						ret.append(comments[j].getAuthor() + " - " + comments[j].getText() + "\n");
+					for (Comment comment : slide.getComments()) {
+						ret.append(comment.getAuthor() + " - " + comment.getText() + "\n");
 					}
 				}
 			}
 			if (getNoteText) {
-				ret.append("\n");
+				ret.append('\n');
 			}
 		}
 
@@ -271,7 +270,7 @@ public final class PowerPointExtractor e
 			// Not currently using _notes, as that can have the notes of
 			// master sheets in. Grab Slide list, then work from there,
 			// but ensure no duplicates
-			HashSet<Integer> seenNotes = new HashSet<Integer>();
+			Set<Integer> seenNotes = new HashSet<Integer>();
             String headerText = "";
             String footerText = "";
 			HeadersFooters hf = _show.getNotesHeadersFooters();
@@ -285,8 +284,8 @@ public final class PowerPointExtractor e
 			}
 			
 
-			for (int i = 0; i < _slides.size(); i++) {
-				HSLFNotes notes = _slides.get(i).getNotes();
+			for (HSLFSlide slide : _slides) {
+				HSLFNotes notes = slide.getNotes();
 				if (notes == null) {
 					continue;
 				}
@@ -297,13 +296,13 @@ public final class PowerPointExtractor e
 				seenNotes.add(id);
 
 				// Repeat the Notes header, if set
-			    ret.append(headerText);
+				ret.append(headerText);
 
 				// Notes text
-                textRunsToText(ret, notes.getTextParagraphs());
+				textRunsToText(ret, notes.getTextParagraphs());
 
 				// Repeat the notes footer, if set
-                ret.append(footerText);
+				ret.append(footerText);
 			}
 		}
 
@@ -315,16 +314,18 @@ public final class PowerPointExtractor e
 	}
 
     private void extractTableText(StringBuffer ret, HSLFTable table) {
-        for (int row = 0; row < table.getNumberOfRows(); row++){
-            for (int col = 0; col < table.getNumberOfColumns(); col++){
+        final int nrows = table.getNumberOfRows();
+        final int ncols = table.getNumberOfColumns();
+        for (int row = 0; row < nrows; row++){
+            for (int col = 0; col < ncols; col++){
                 HSLFTableCell cell = table.getCell(row, col);
                 //defensive null checks; don't know if they're necessary
                 if (cell != null){
                     String txt = cell.getText();
                     txt = (txt == null) ? "" : txt;
                     ret.append(txt);
-                    if (col < table.getNumberOfColumns()-1){
-                        ret.append("\t");
+                    if (col < ncols-1){
+                        ret.append('\t');
                     }
                 }
             }
@@ -339,7 +340,7 @@ public final class PowerPointExtractor e
         for (List<HSLFTextParagraph> lp : paragraphs) {
             ret.append(HSLFTextParagraph.getText(lp));
             if (ret.length() > 0 && ret.charAt(ret.length()-1) != '\n') {
-                ret.append("\n");
+                ret.append('\n');
             }
         }
     }

Modified: poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java?rev=1756967&r1=1756966&r2=1756967&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java (original)
+++ poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java Fri Aug 19 20:57:56 2016
@@ -36,6 +36,8 @@ import org.apache.poi.hslf.usermodel.HSL
  */
 public final class HeadersFooters {
 
+    private static final String _ppt2007tag = "___PPT12";
+
     private final HeadersFootersContainer _container;
     private final HSLFSheet _sheet;
     private final boolean _ppt2007;
@@ -54,7 +56,7 @@ public final class HeadersFooters {
         
         // detect if this ppt was saved in Office2007
         String tag = ppt.getSlideMasters().get(0).getProgrammableTag();
-        _ppt2007 = "___PPT12".equals(tag);
+        _ppt2007 = _ppt2007tag.equals(tag);
 
         SheetContainer sc = _sheet.getSheetContainer();
         HeadersFootersContainer hdd = (HeadersFootersContainer)sc.findFirstOfType(RecordTypes.HeadersFooters.typeID);




---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org