Return-Path: X-Original-To: apmail-poi-commits-archive@minotaur.apache.org Delivered-To: apmail-poi-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 301FC18234 for ; Wed, 17 Jun 2015 22:21:15 +0000 (UTC) Received: (qmail 1790 invoked by uid 500); 17 Jun 2015 22:21:15 -0000 Delivered-To: apmail-poi-commits-archive@poi.apache.org Received: (qmail 1754 invoked by uid 500); 17 Jun 2015 22:21:15 -0000 Mailing-List: contact commits-help@poi.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@poi.apache.org Delivered-To: mailing list commits@poi.apache.org Received: (qmail 1745 invoked by uid 99); 17 Jun 2015 22:21:15 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 17 Jun 2015 22:21:15 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id EC76CAC00B4 for ; Wed, 17 Jun 2015 22:21:14 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1686117 [1/3] - in /poi/branches/common_sl: src/examples/src/org/apache/poi/hslf/examples/ src/examples/src/org/apache/poi/xslf/usermodel/ src/java/org/apache/poi/util/ src/ooxml/java/org/apache/poi/xslf/usermodel/ src/ooxml/testcases/org/... Date: Wed, 17 Jun 2015 22:21:14 -0000 To: commits@poi.apache.org From: kiwiwings@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150617222114.EC76CAC00B4@hades.apache.org> Author: kiwiwings Date: Wed Jun 17 22:21:13 2015 New Revision: 1686117 URL: http://svn.apache.org/r1686117 Log: Rendering fixes Added: poi/branches/common_sl/test-data/slideshow/alterman_security2.pptx (with props) Modified: poi/branches/common_sl/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java poi/branches/common_sl/src/java/org/apache/poi/util/Units.java poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideMaster.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextParagraph.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/sl/usermodel/TextParagraph.java poi/branches/common_sl/src/scratchpad/src/org/apache/poi/sl/usermodel/TextRun.java poi/branches/common_sl/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java poi/branches/common_sl/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java poi/branches/common_sl/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java Modified: poi/branches/common_sl/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java (original) +++ poi/branches/common_sl/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java Wed Jun 17 22:21:13 2015 @@ -39,8 +39,8 @@ public final class BulletsDemo { HSLFTextParagraph rt = shape.getTextParagraphs().get(0); rt.getTextRuns().get(0).setFontSize(42); rt.setBullet(true); - rt.setIndent(0); //bullet offset - rt.setLeftMargin(50); //text offset (should be greater than bullet offset) + rt.setIndent(0d); //bullet offset + rt.setLeftMargin(50d); //text offset (should be greater than bullet offset) rt.setBulletChar('\u263A'); //bullet character shape.setText( "January\r" + Modified: poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java (original) +++ poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial2.java Wed Jun 17 22:21:13 2015 @@ -48,8 +48,8 @@ public class Tutorial2 { XSLFTextParagraph p2 = shape1.addNewTextParagraph(); // If spaceBefore >= 0, then space is a percentage of normal line height. // If spaceBefore < 0, the absolute value of linespacing is the spacing in points - p2.setSpaceBefore(-20); // 20 pt from the previous paragraph - p2.setSpaceAfter(300); // 3 lines after the paragraph + p2.setSpaceBefore(-20d); // 20 pt from the previous paragraph + p2.setSpaceAfter(300d); // 3 lines after the paragraph XSLFTextRun r2 = p2.addNewTextRun(); r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph."); r2.setFontSize(16); @@ -62,8 +62,8 @@ public class Tutorial2 { r3.setFontColor(new Color(85, 142, 213)); XSLFTextParagraph p4 = shape1.addNewTextParagraph(); - p4.setSpaceBefore(-20); // 20 pt from the previous paragraph - p4.setSpaceAfter(300); // 3 lines after the paragraph + p4.setSpaceBefore(-20d); // 20 pt from the previous paragraph + p4.setSpaceAfter(300d); // 3 lines after the paragraph XSLFTextRun r4 = p4.addNewTextRun(); r4.setFontSize(16); r4.setText( Modified: poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java (original) +++ poi/branches/common_sl/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial7.java Wed Jun 17 22:21:13 2015 @@ -45,9 +45,9 @@ public class Tutorial7 { XSLFTextParagraph p2 = shape.addNewTextParagraph(); // indentation before text - p2.setLeftMargin(60); + p2.setLeftMargin(60d); // the bullet is set 40 pt before the text - p2.setIndent(-40); + p2.setIndent(-40d); p2.setBullet(true); // customize bullets p2.setBulletFontColor(Color.red); Modified: poi/branches/common_sl/src/java/org/apache/poi/util/Units.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/util/Units.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/java/org/apache/poi/util/Units.java (original) +++ poi/branches/common_sl/src/java/org/apache/poi/util/Units.java Wed Jun 17 22:21:13 2015 @@ -16,6 +16,8 @@ ==================================================================== */ package org.apache.poi.util; +import org.apache.poi.hslf.usermodel.HSLFShape; + /** * @author Yegor Kozlov */ @@ -24,6 +26,22 @@ public class Units { public static final int EMU_PER_POINT = 12700; /** + * Master DPI (576 pixels per inch). + * Used by the reference coordinate system in PowerPoint (HSLF) + */ + public static final int MASTER_DPI = 576; + + /** + * Pixels DPI (96 pixels per inch) + */ + public static final int PIXEL_DPI = 96; + + /** + * Points DPI (72 pixels per inch) + */ + public static final int POINT_DPI = 72; + + /** * Converts points to EMUs * @param points points * @return emus @@ -70,4 +88,17 @@ public class Units { int fixedPoint = (i << 16) | (f & 0xFFFF); return fixedPoint; } + + public static double masterToPoints(int masterDPI) { + double points = masterDPI; + points *= HSLFShape.POINT_DPI; + points /= HSLFShape.MASTER_DPI; + return points; + } + + public static int pointsToMaster(double points) { + points *= HSLFShape.MASTER_DPI; + points /= HSLFShape.POINT_DPI; + return (int)points; + } } Modified: poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java (original) +++ poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java Wed Jun 17 22:21:13 2015 @@ -137,8 +137,10 @@ public class XSLFTextParagraph implement /** * Returns the alignment that is applied to the paragraph. * - * If this attribute is omitted, then a value of left is implied. - * @return ??? alignment that is applied to the paragraph + * If this attribute is omitted, then null is returned. + * User code can imply the value {@link TextAlign#LEFT} then. + * + * @return alignment that is applied to the paragraph */ public TextAlign getTextAlign(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ @@ -152,7 +154,7 @@ public class XSLFTextParagraph implement } }; fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? TextAlign.LEFT : fetcher.getValue(); + return fetcher.getValue(); } /** @@ -184,7 +186,7 @@ public class XSLFTextParagraph implement } }; fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? FontAlign.AUTO : fetcher.getValue(); + return fetcher.getValue(); } /** @@ -294,7 +296,7 @@ public class XSLFTextParagraph implement * * @return the bullet size */ - public double getBulletFontSize(){ + public Double getBulletFontSize(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetBuSzPct()){ @@ -309,7 +311,7 @@ public class XSLFTextParagraph implement } }; fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 100 : fetcher.getValue(); + return fetcher.getValue(); } /** @@ -334,27 +336,19 @@ public class XSLFTextParagraph implement } } - /** - * Specifies the indent size that will be applied to the first line of text in the paragraph. - * - * @param value the indent in points. - */ @Override - public void setIndent(double value){ + public void setIndent(Double indent){ + if (indent == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(value == -1) { + if(indent == -1) { if(pr.isSetIndent()) pr.unsetIndent(); } else { - pr.setIndent(Units.toEMU(value)); + pr.setIndent(Units.toEMU(indent)); } } - /** - * - * @return the indent applied to the first line of text in the paragraph. - */ @Override - public double getIndent(){ + public Double getIndent() { ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ @@ -367,32 +361,26 @@ public class XSLFTextParagraph implement }; fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); + return fetcher.getValue(); } - /** - * Specifies the left margin of the paragraph. This is specified in addition to the text body - * inset and applies only to this text paragraph. That is the text body Inset and the LeftMargin - * attributes are additive with respect to the text position. - * - * @param value the left margin (in points) of the paragraph - */ @Override - public void setLeftMargin(double value){ + public void setLeftMargin(Double leftMargin){ + if (leftMargin == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(value == -1) { + if (leftMargin == null) { if(pr.isSetMarL()) pr.unsetMarL(); } else { - pr.setMarL(Units.toEMU(value)); + pr.setMarL(Units.toEMU(leftMargin)); } } /** - * @return the left margin (in points) of the paragraph + * @return the left margin (in points) of the paragraph, null if unset */ @Override - public double getLeftMargin(){ + public Double getLeftMargin(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetMarL()){ @@ -405,32 +393,26 @@ public class XSLFTextParagraph implement }; fetchParagraphProperty(fetcher); // if the marL attribute is omitted, then a value of 347663 is implied - return fetcher.getValue() == null ? 0 : fetcher.getValue(); + return fetcher.getValue(); } - /** - * Specifies the right margin of the paragraph. This is specified in addition to the text body - * inset and applies only to this text paragraph. That is the text body Inset and the RightMargin - * attributes are additive with respect to the text position. - * - * @param value the right margin (in points) of the paragraph - */ @Override - public void setRightMargin(double value){ + public void setRightMargin(Double rightMargin){ + if (rightMargin == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(value == -1) { + if(rightMargin == -1) { if(pr.isSetMarR()) pr.unsetMarR(); } else { - pr.setMarR(Units.toEMU(value)); + pr.setMarR(Units.toEMU(rightMargin)); } } /** * - * @return the right margin of the paragraph + * @return the right margin of the paragraph, null if unset */ @Override - public double getRightMargin(){ + public Double getRightMargin(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetMarR()){ @@ -443,14 +425,11 @@ public class XSLFTextParagraph implement }; fetchParagraphProperty(fetcher); // if the marL attribute is omitted, then a value of 347663 is implied - return fetcher.getValue() == null ? 0 : fetcher.getValue(); + return fetcher.getValue(); } - /** - * - * @return the default size for a tab character within this paragraph in points - */ - public double getDefaultTabSize(){ + @Override + public Double getDefaultTabSize(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetDefTabSz()){ @@ -462,7 +441,7 @@ public class XSLFTextParagraph implement } }; fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); + return fetcher.getValue(); } public double getTabStop(final int idx){ @@ -491,16 +470,25 @@ public class XSLFTextParagraph implement } @Override - public void setLineSpacing(double linespacing){ + public void setLineSpacing(Double lineSpacing){ + if (lineSpacing == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); - if(linespacing >= 0) spc.addNewSpcPct().setVal((int)(linespacing*1000)); - else spc.addNewSpcPts().setVal((int)(-linespacing*100)); - pr.setLnSpc(spc); + 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(){ + public Double getLineSpacing(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetLnSpc()){ @@ -515,8 +503,8 @@ public class XSLFTextParagraph implement }; fetchParagraphProperty(fetcher); - double lnSpc = fetcher.getValue() == null ? 100 : fetcher.getValue(); - if(lnSpc > 0) { + Double lnSpc = fetcher.getValue(); + if (lnSpc != null && lnSpc > 0) { // check if the percentage value is scaled CTTextNormalAutofit normAutofit = getParentShape().getTextBodyPr().getNormAutofit(); if(normAutofit != null) { @@ -528,26 +516,9 @@ public class XSLFTextParagraph implement return lnSpc; } - /** - * Set the amount of vertical white space that will be present before the paragraph. - * This space is specified in either percentage or points: - *

- * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - *

- * Examples: - *

-     *      // The paragraph will be formatted to have a spacing before the paragraph text.
-     *      // The spacing will be 200% of the size of the largest text on each line
-     *      paragraph.setSpaceBefore(200);
-     *
-     *      // The spacing will be a size of 48 points
-     *      paragraph.setSpaceBefore(-48.0);
-     * 
- * - * @param spaceBefore the vertical white space before the paragraph. - */ - public void setSpaceBefore(double spaceBefore){ + @Override + public void setSpaceBefore(Double spaceBefore){ + if (spaceBefore == null && !_p.isSetPPr()) return; CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); if(spaceBefore >= 0) spc.addNewSpcPct().setVal((int)(spaceBefore*1000)); @@ -555,17 +526,8 @@ public class XSLFTextParagraph implement pr.setSpcBef(spc); } - /** - * The amount of vertical white space before the paragraph - * This may be specified in two different ways, percentage spacing and font point spacing: - *

- * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - *

- * - * @return the vertical white space before the paragraph - */ - public double getSpaceBefore(){ + @Override + public Double getSpaceBefore(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetSpcBef()){ @@ -580,30 +542,11 @@ public class XSLFTextParagraph implement }; fetchParagraphProperty(fetcher); - double spcBef = fetcher.getValue() == null ? 0 : fetcher.getValue(); - return spcBef; + return fetcher.getValue(); } - /** - * Set the amount of vertical white space that will be present after the paragraph. - * This space is specified in either percentage or points: - *

- * If spaceAfter >= 0, then space is a percentage of normal line height. - * If spaceAfter < 0, the absolute value of linespacing is the spacing in points - *

- * Examples: - *

-     *      // The paragraph will be formatted to have a spacing after the paragraph text.
-     *      // The spacing will be 200% of the size of the largest text on each line
-     *      paragraph.setSpaceAfter(200);
-     *
-     *      // The spacing will be a size of 48 points
-     *      paragraph.setSpaceAfter(-48.0);
-     * 
- * - * @param spaceAfter the vertical white space after the paragraph. - */ - public void setSpaceAfter(double spaceAfter){ + @Override + public void setSpaceAfter(Double spaceAfter){ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); if(spaceAfter >= 0) spc.addNewSpcPct().setVal((int)(spaceAfter*1000)); @@ -611,17 +554,8 @@ public class XSLFTextParagraph implement pr.setSpcAft(spc); } - /** - * The amount of vertical white space after the paragraph - * This may be specified in two different ways, percentage spacing and font point spacing: - *

- * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - *

- * - * @return the vertical white space after the paragraph - */ - public double getSpaceAfter(){ + @Override + public Double getSpaceAfter(){ ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ if(props.isSetSpcAft()){ @@ -635,7 +569,7 @@ public class XSLFTextParagraph implement } }; fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); + return fetcher.getValue(); } /** @@ -647,7 +581,6 @@ public class XSLFTextParagraph implement */ public void setLevel(int level){ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - pr.setLvl(level); } @@ -657,10 +590,7 @@ public class XSLFTextParagraph implement */ public int getLevel(){ CTTextParagraphProperties pr = _p.getPPr(); - if(pr == null) return 0; - - return pr.getLvl(); - + return (pr == null || !pr.isSetLvl()) ? 0 : pr.getLvl(); } /** @@ -721,53 +651,70 @@ public class XSLFTextParagraph implement } - CTTextParagraphProperties getDefaultMasterStyle(){ + /* package */ CTTextParagraphProperties getDefaultMasterStyle(){ CTPlaceholder ph = _shape.getCTPlaceholder(); - String defaultStyleSelector; - if(ph == null) defaultStyleSelector = "otherStyle"; // no placeholder means plain text box - else { - switch(ph.getType().intValue()){ - case STPlaceholderType.INT_TITLE: - case STPlaceholderType.INT_CTR_TITLE: - defaultStyleSelector = "titleStyle"; - break; - case STPlaceholderType.INT_FTR: - case STPlaceholderType.INT_SLD_NUM: - case STPlaceholderType.INT_DT: - defaultStyleSelector = "otherStyle"; - break; - default: - defaultStyleSelector = "bodyStyle"; - break; - } + 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 = getLevel(); // wind up and find the root master sheet which must be slide master XSLFSheet masterSheet = _shape.getSheet(); - while (masterSheet.getMasterSheet() != null){ - masterSheet = (XSLFSheet)masterSheet.getMasterSheet(); + for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) { + masterSheet = m; } - XmlObject[] o = masterSheet.getXmlObject().selectPath( - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + - "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + - ".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr"); - if (o.length == 1){ - return (CTTextParagraphProperties)o[0]; - } else { - o = masterSheet.getXmlObject().selectPath( - "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + - "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + - ".//p:notesStyle/a:lvl" +(level+1)+ "pPr"); - - if (o.length == 1){ + String nsDecl = + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + + "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' "; + String xpaths[] = { + nsDecl+".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr", + nsDecl+".//p:notesStyle/a:lvl" +(level+1)+ "pPr" + }; + XmlObject xo = masterSheet.getXmlObject(); + for (String xpath : xpaths) { + XmlObject[] o = xo.selectPath(xpath); + if (o.length == 1) { return (CTTextParagraphProperties)o[0]; } - - throw new IllegalArgumentException("Failed to fetch default style for " + - defaultStyleSelector + " and level=" + level); } + +// for (CTTextBody txBody : (CTTextBody[])xo.selectPath(nsDecl+".//p:txBody")) { +// CTTextParagraphProperties defaultPr = null, lastPr = null; +// boolean hasLvl = false; +// for (CTTextParagraph p : txBody.getPArray()) { +// CTTextParagraphProperties pr = p.getPPr(); +// if (pr.isSetLvl()) { +// hasLvl |= true; +// lastPr = pr; +// if (pr.getLvl() == level) return pr; +// } else { +// defaultPr = pr; +// } +// } +// if (!hasLvl) continue; +// if (level == 0 && defaultPr != null) return defaultPr; +// if (lastPr != null) return lastPr; +// break; +// } +// +// String err = "Failed to fetch default style for " + defaultStyleSelector + " and level=" + level; +// throw new IllegalArgumentException(err); + + return null; } private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){ @@ -860,9 +807,9 @@ public class XSLFTextParagraph implement } @Override - public double getDefaultFontSize() { + public Double getDefaultFontSize() { CTTextCharacterProperties endPr = _p.getEndParaRPr(); - return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100); + return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.); } @Override @@ -871,6 +818,7 @@ public class XSLFTextParagraph implement } public BulletStyle getBulletStyle() { + if (!isBullet()) return null; return new BulletStyle(){ public String getBulletCharacter() { return XSLFTextParagraph.this.getBulletCharacter(); @@ -880,7 +828,7 @@ public class XSLFTextParagraph implement return XSLFTextParagraph.this.getBulletFont(); } - public double getBulletFontSize() { + public Double getBulletFontSize() { return XSLFTextParagraph.this.getBulletFontSize(); } Modified: poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java (original) +++ poi/branches/common_sl/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java Wed Jun 17 22:21:13 2015 @@ -17,26 +17,11 @@ package org.apache.poi.xslf.usermodel; import java.awt.Color; -import java.awt.font.FontRenderContext; -import java.awt.font.TextAttribute; -import java.awt.font.TextLayout; -import java.text.AttributedString; import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.util.Beta; import org.apache.poi.xslf.model.CharacterPropertyFetcher; -import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; +import org.openxmlformats.schemas.drawingml.x2006.main.*; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; /** @@ -89,28 +74,6 @@ public class XSLFTextRun implements Text return buf.toString(); } - /** - * Replace a tab with the effective number of white spaces. - */ - private String tab2space(){ - AttributedString string = new AttributedString(" "); - // user can pass an object to convert fonts via a rendering hint - string.addAttribute(TextAttribute.FAMILY, getFontFamily()); - - string.addAttribute(TextAttribute.SIZE, (float)getFontSize()); - TextLayout l = new TextLayout(string.getIterator(), new FontRenderContext(null, true, true)); - double wspace = l.getAdvance(); - - double tabSz = _p.getDefaultTabSize(); - - int numSpaces = (int)Math.ceil(tabSz / wspace); - StringBuffer buf = new StringBuffer(); - for(int i = 0; i < numSpaces; i++) { - buf.append(' '); - } - return buf.toString(); - } - public void setText(String text){ _r.setT(text); } @@ -175,9 +138,10 @@ public class XSLFTextRun implements Text } /** - * @return font size in points or -1 if font size is not set. + * @return font size in points or null if font size is not set. */ - public double getFontSize(){ + @Override + public Double getFontSize(){ double scale = 1; CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit(); if(afit != null) scale = (double)afit.getFontScale() / 100000; @@ -192,7 +156,7 @@ public class XSLFTextRun implements Text } }; fetchCharacterProperty(fetcher); - return fetcher.getValue() == null ? -1 : fetcher.getValue()*scale; + return fetcher.getValue() == null ? null : fetcher.getValue()*scale; } /** @@ -514,7 +478,7 @@ public class XSLFTextRun implements Text return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this); } - private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){ + private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){ boolean ok = false; if(_r.isSetRPr()) ok = fetcher.fetch(getRPr()); Modified: poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java (original) +++ poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java Wed Jun 17 22:21:13 2015 @@ -125,7 +125,7 @@ public class TestXSLFAutoShape { p.setIndent(2.0); assertEquals(2.0, p.getIndent(), 0); assertTrue(p.getXmlObject().getPPr().isSetIndent()); - p.setIndent(-1); + p.setIndent(-1d); assertEquals(0.0, p.getIndent(), 0); assertFalse(p.getXmlObject().getPPr().isSetIndent()); p.setIndent(10.0); @@ -149,44 +149,44 @@ public class TestXSLFAutoShape { assertFalse(p.getXmlObject().getPPr().isSetSpcAft()); - p.setSpaceAfter(200); + p.setSpaceAfter(200d); assertEquals(200000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); - p.setSpaceAfter(100); + p.setSpaceAfter(100d); assertEquals(100000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); - p.setSpaceAfter(-20); + p.setSpaceAfter(-20d); assertEquals(2000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); - p.setSpaceAfter(-10); + p.setSpaceAfter(-10d); assertEquals(1000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().isSetSpcBef()); - p.setSpaceBefore(200); + p.setSpaceBefore(200d); assertEquals(200000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); - p.setSpaceBefore(100); + p.setSpaceBefore(100d); assertEquals(100000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); - p.setSpaceBefore(-20); + p.setSpaceBefore(-20d); assertEquals(2000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); - p.setSpaceBefore(-10); + p.setSpaceBefore(-10d); assertEquals(1000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().isSetLnSpc()); - p.setLineSpacing(200); + p.setLineSpacing(200d); assertEquals(200000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); - p.setLineSpacing(100); + p.setLineSpacing(100d); assertEquals(100000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); - p.setLineSpacing(-20); + p.setLineSpacing(-20d); assertEquals(2000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); - p.setLineSpacing(-10); + p.setLineSpacing(-10d); assertEquals(1000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); Modified: poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java (original) +++ poi/branches/common_sl/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java Wed Jun 17 22:21:13 2015 @@ -92,7 +92,7 @@ public class TestXSLFTextParagraph { assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); - p.setLeftMargin(36); // 0.5" + p.setLeftMargin(36d); // 0.5" leftMargin = p.getLeftMargin(); assertEquals(36.0, leftMargin, 0); expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; Modified: poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java (original) +++ poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java Wed Jun 17 22:21:13 2015 @@ -21,12 +21,13 @@ package org.apache.poi.hslf.model.textpr * Definition for the font alignment property. */ public class FontAlignmentProp extends TextProp { + public static final String NAME = "fontAlign"; public static final int BASELINE = 0; public static final int TOP = 1; public static final int CENTER = 2; public static final int BOTTOM = 3; public FontAlignmentProp() { - super(2, 0x10000, "fontAlign"); + super(2, 0x10000, NAME); } } \ No newline at end of file Modified: poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java (original) +++ poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java Wed Jun 17 22:21:13 2015 @@ -31,47 +31,10 @@ import org.apache.poi.util.LittleEndian; * properties, and the indent level if required. */ public class TextPropCollection { - /* - private static TextProp paragraphSpecialPropTypes[] = { - new ParagraphFlagsTextProp(), - new TextProp(2, 0x80, "bullet.char"), - new TextProp(2, 0x10, "bullet.font"), - new TextProp(2, 0x40, "bullet.size"), - new TextProp(4, 0x20, "bullet.color"), - new TextProp(2, 0xD00, "alignment"), - new TextProp(2, 0x1000, "linespacing"), - new TextProp(2, 0x2000, "spacebefore"), - new TextProp(2, 0x4000, "spaceafter"), - new TextProp(2, 0x8000, "text.offset"), - new TextProp(2, 0x10000, "bullet.offset"), - new TextProp(2, 0x20000, "defaulttab"), - new TextProp(2, 0x40000, "para_unknown_2"), - new TextProp(2, 0x80000, "para_unknown_3"), - new TextProp(2, 0x100000, "para_unknown_4"), - new TextProp(2, 0x200000, "para_unknown_5") - }; - - private static TextProp characterSpecialPropTypes[] = { - new CharFlagsTextProp(), - new TextProp(2, 0x10000, "font.index"), - new TextProp(2, 0x20000, "char_unknown_1"), - new TextProp(4, 0x40000, "char_unknown_2"), - new TextProp(2, 0x80000, "font.size"), - new TextProp(2, 0x100000, "char_unknown_3"), - new TextProp(4, 0x200000, "font.color"), - new TextProp(2, 0x800000, "char_unknown_4") - }; -*/ - - /** All the different kinds of paragraph properties we might handle */ public static final TextProp[] paragraphTextPropTypes = { // TextProp order is according to 2.9.20 TextPFException, // bitmask order can be different -// new TextProp(0, 0x1, "hasBullet"), -// new TextProp(0, 0x2, "hasBulletFont"), -// new TextProp(0, 0x4, "hasBulletColor"), -// new TextProp(0, 0x8, "hasBulletSize"), new ParagraphFlagsTextProp(), new TextProp(2, 0x80, "bullet.char"), new TextProp(2, 0x10, "bullet.font"), @@ -95,24 +58,9 @@ public class TextPropCollection { new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size // 0xFC000000 MUST be zero and MUST be ignored }; + /** All the different kinds of character properties we might handle */ public static final TextProp[] characterTextPropTypes = new TextProp[] { -// new TextProp(0, 0x1, "bold"), -// new TextProp(0, 0x2, "italic"), -// new TextProp(0, 0x4, "underline"), -// new TextProp(0, 0x8, "unused1"), -// new TextProp(0, 0x10, "shadow"), -// new TextProp(0, 0x20, "fehint"), -// new TextProp(0, 0x40, "unused2"), -// new TextProp(0, 0x80, "kumi"), -// new TextProp(0, 0x100, "strikethrough"), -// new TextProp(0, 0x200, "emboss"), -// new TextProp(0, 0x400, "nibble1"), -// new TextProp(0, 0x800, "nibble2"), -// new TextProp(0, 0x1000, "nibble3"), -// new TextProp(0, 0x2000, "nibble4"), -// new TextProp(0, 0x4000, "unused4"), -// new TextProp(0, 0x8000, "unused5"), new TextProp(0, 0x100000, "pp10ext"), new TextProp(0, 0x1000000, "newAsian.font.index"), // A bit that specifies whether the newEAFontRef field of the TextCFException10 structure that contains this CFMasks exists. new TextProp(0, 0x2000000, "cs.font.index"), // A bit that specifies whether the csFontRef field of the TextCFException10 structure that contains this CFMasks exists. @@ -166,6 +114,19 @@ public class TextPropCollection { } return null; } + + public TextProp removeByName(String name) { + Iterator iter = textPropList.iterator(); + TextProp tp = null; + while (iter.hasNext()) { + tp = iter.next(); + if (tp.getName().equals(name)){ + iter.remove(); + break; + } + } + return tp; + } /** Add the TextProp with this name to the list */ public TextProp addWithName(String name) { @@ -192,6 +153,10 @@ public class TextPropCollection { return textProp; } + public TextPropType getTextPropType() { + return textPropType; + } + private TextProp[] getPotentialProperties() { return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes; } Modified: poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java (original) +++ poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java Wed Jun 17 22:21:13 2015 @@ -17,6 +17,7 @@ package org.apache.poi.hslf.record; +import org.apache.poi.hslf.model.PPFont; import org.apache.poi.util.POILogger; import java.io.*; @@ -75,9 +76,9 @@ public final class FontCollection extend */ public int addFont(String name) { int idx = getFontIndex(name); - if(idx != -1) return idx; + if (idx != -1) return idx; - return addFont(name, 0, 0, 4, 34); + return addFont(name, 0, 0, 4, PPFont.FF_SWISS | PPFont.VARIABLE_PITCH); } public int addFont(String name, int charset, int flags, int type, int pitch) { Modified: poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideMaster.java URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideMaster.java?rev=1686117&r1=1686116&r2=1686117&view=diff ============================================================================== --- poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideMaster.java (original) +++ poi/branches/common_sl/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideMaster.java Wed Jun 17 22:21:13 2015 @@ -76,45 +76,31 @@ public final class HSLFSlideMaster exten * This is the "workhorse" which returns the default style attrubutes. */ public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) { - + if (_txmaster.length <= txtype) return null; + TxMasterStyleAtom t = _txmaster[txtype]; + List styles = isCharacter ? t.getCharacterStyles() : t.getParagraphStyles(); + TextProp prop = null; - for (int i = level; i >= 0; i--) { - List styles = - isCharacter ? _txmaster[txtype].getCharacterStyles() : _txmaster[txtype].getParagraphStyles(); - if (i < styles.size()) prop = styles.get(i).findByName(name); - if (prop != null) break; + for (int i = Math.min(level, styles.size()-1); prop == null && i >= 0; i--) { + prop = styles.get(i).findByName(name); } - if (prop == null) { - if(isCharacter) { - switch (txtype) { - case TextHeaderAtom.CENTRE_BODY_TYPE: - case TextHeaderAtom.HALF_BODY_TYPE: - case TextHeaderAtom.QUARTER_BODY_TYPE: - txtype = TextHeaderAtom.BODY_TYPE; - break; - case TextHeaderAtom.CENTER_TITLE_TYPE: - txtype = TextHeaderAtom.TITLE_TYPE; - break; - default: - return null; - } - } else { - switch (txtype) { - case TextHeaderAtom.CENTRE_BODY_TYPE: - case TextHeaderAtom.HALF_BODY_TYPE: - case TextHeaderAtom.QUARTER_BODY_TYPE: - txtype = TextHeaderAtom.BODY_TYPE; - break; - case TextHeaderAtom.CENTER_TITLE_TYPE: - txtype = TextHeaderAtom.TITLE_TYPE; - break; - default: - return null; - } - } - prop = getStyleAttribute(txtype, level, name, isCharacter); + + if (prop != null) return prop; + + switch (txtype) { + case TextHeaderAtom.CENTRE_BODY_TYPE: + case TextHeaderAtom.HALF_BODY_TYPE: + case TextHeaderAtom.QUARTER_BODY_TYPE: + txtype = TextHeaderAtom.BODY_TYPE; + break; + case TextHeaderAtom.CENTER_TITLE_TYPE: + txtype = TextHeaderAtom.TITLE_TYPE; + break; + default: + return null; } - return prop; + + return getStyleAttribute(txtype, level, name, isCharacter); } /** --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org For additional commands, e-mail: commits-help@poi.apache.org