Rendering fixes

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1686117 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2015-06-17 22:21:13 +00:00
parent 2170a52383
commit f97d6f6c34
22 changed files with 1192 additions and 1197 deletions

View File

@ -39,8 +39,8 @@ public final class BulletsDemo {
HSLFTextParagraph rt = shape.getTextParagraphs().get(0); HSLFTextParagraph rt = shape.getTextParagraphs().get(0);
rt.getTextRuns().get(0).setFontSize(42); rt.getTextRuns().get(0).setFontSize(42);
rt.setBullet(true); rt.setBullet(true);
rt.setIndent(0); //bullet offset rt.setIndent(0d); //bullet offset
rt.setLeftMargin(50); //text offset (should be greater than bullet offset) rt.setLeftMargin(50d); //text offset (should be greater than bullet offset)
rt.setBulletChar('\u263A'); //bullet character rt.setBulletChar('\u263A'); //bullet character
shape.setText( shape.setText(
"January\r" + "January\r" +

View File

@ -48,8 +48,8 @@ public class Tutorial2 {
XSLFTextParagraph p2 = shape1.addNewTextParagraph(); XSLFTextParagraph p2 = shape1.addNewTextParagraph();
// If spaceBefore >= 0, then space is a percentage of normal line height. // 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 // If spaceBefore < 0, the absolute value of linespacing is the spacing in points
p2.setSpaceBefore(-20); // 20 pt from the previous paragraph p2.setSpaceBefore(-20d); // 20 pt from the previous paragraph
p2.setSpaceAfter(300); // 3 lines after the paragraph p2.setSpaceAfter(300d); // 3 lines after the paragraph
XSLFTextRun r2 = p2.addNewTextRun(); XSLFTextRun r2 = p2.addNewTextRun();
r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph."); r2.setText("Paragraph properties apply to all text residing within the corresponding paragraph.");
r2.setFontSize(16); r2.setFontSize(16);
@ -62,8 +62,8 @@ public class Tutorial2 {
r3.setFontColor(new Color(85, 142, 213)); r3.setFontColor(new Color(85, 142, 213));
XSLFTextParagraph p4 = shape1.addNewTextParagraph(); XSLFTextParagraph p4 = shape1.addNewTextParagraph();
p4.setSpaceBefore(-20); // 20 pt from the previous paragraph p4.setSpaceBefore(-20d); // 20 pt from the previous paragraph
p4.setSpaceAfter(300); // 3 lines after the paragraph p4.setSpaceAfter(300d); // 3 lines after the paragraph
XSLFTextRun r4 = p4.addNewTextRun(); XSLFTextRun r4 = p4.addNewTextRun();
r4.setFontSize(16); r4.setFontSize(16);
r4.setText( r4.setText(

View File

@ -45,9 +45,9 @@ public class Tutorial7 {
XSLFTextParagraph p2 = shape.addNewTextParagraph(); XSLFTextParagraph p2 = shape.addNewTextParagraph();
// indentation before text // indentation before text
p2.setLeftMargin(60); p2.setLeftMargin(60d);
// the bullet is set 40 pt before the text // the bullet is set 40 pt before the text
p2.setIndent(-40); p2.setIndent(-40d);
p2.setBullet(true); p2.setBullet(true);
// customize bullets // customize bullets
p2.setBulletFontColor(Color.red); p2.setBulletFontColor(Color.red);

View File

@ -16,6 +16,8 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.util; package org.apache.poi.util;
import org.apache.poi.hslf.usermodel.HSLFShape;
/** /**
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
@ -23,6 +25,22 @@ public class Units {
public static final int EMU_PER_PIXEL = 9525; public static final int EMU_PER_PIXEL = 9525;
public static final int EMU_PER_POINT = 12700; 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 * Converts points to EMUs
* @param points points * @param points points
@ -70,4 +88,17 @@ public class Units {
int fixedPoint = (i << 16) | (f & 0xFFFF); int fixedPoint = (i << 16) | (f & 0xFFFF);
return fixedPoint; 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;
}
} }

View File

@ -137,8 +137,10 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
/** /**
* Returns the alignment that is applied to the paragraph. * Returns the alignment that is applied to the paragraph.
* *
* If this attribute is omitted, then a value of left is implied. * If this attribute is omitted, then null is returned.
* @return ??? alignment that is applied to the paragraph * User code can imply the value {@link TextAlign#LEFT} then.
*
* @return alignment that is applied to the paragraph
*/ */
public TextAlign getTextAlign(){ public TextAlign getTextAlign(){
ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getLevel()){ ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getLevel()){
@ -152,7 +154,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? TextAlign.LEFT : fetcher.getValue(); return fetcher.getValue();
} }
/** /**
@ -184,7 +186,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? FontAlign.AUTO : fetcher.getValue(); return fetcher.getValue();
} }
/** /**
@ -294,7 +296,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
* *
* @return the bullet size * @return the bullet size
*/ */
public double getBulletFontSize(){ public Double getBulletFontSize(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuSzPct()){ if(props.isSetBuSzPct()){
@ -309,7 +311,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 100 : fetcher.getValue(); return fetcher.getValue();
} }
/** /**
@ -334,27 +336,19 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
} }
/**
* Specifies the indent size that will be applied to the first line of text in the paragraph.
*
* @param value the indent in points.
*/
@Override @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(); CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
if(value == -1) { if(indent == -1) {
if(pr.isSetIndent()) pr.unsetIndent(); if(pr.isSetIndent()) pr.unsetIndent();
} else { } 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 @Override
public double getIndent(){ public Double getIndent() {
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
@ -367,32 +361,26 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
}; };
fetchParagraphProperty(fetcher); 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 @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(); CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
if(value == -1) { if (leftMargin == null) {
if(pr.isSetMarL()) pr.unsetMarL(); if(pr.isSetMarL()) pr.unsetMarL();
} else { } 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 @Override
public double getLeftMargin(){ public Double getLeftMargin(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetMarL()){ if(props.isSetMarL()){
@ -405,32 +393,26 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
// if the marL attribute is omitted, then a value of 347663 is implied // 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 @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(); CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
if(value == -1) { if(rightMargin == -1) {
if(pr.isSetMarR()) pr.unsetMarR(); if(pr.isSetMarR()) pr.unsetMarR();
} else { } 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 @Override
public double getRightMargin(){ public Double getRightMargin(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetMarR()){ if(props.isSetMarR()){
@ -443,14 +425,11 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
// if the marL attribute is omitted, then a value of 347663 is implied // if the marL attribute is omitted, then a value of 347663 is implied
return fetcher.getValue() == null ? 0 : fetcher.getValue(); return fetcher.getValue();
} }
/** @Override
* public Double getDefaultTabSize(){
* @return the default size for a tab character within this paragraph in points
*/
public double getDefaultTabSize(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetDefTabSz()){ if(props.isSetDefTabSz()){
@ -462,7 +441,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue(); return fetcher.getValue();
} }
public double getTabStop(final int idx){ public double getTabStop(final int idx){
@ -491,16 +470,25 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
@Override @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(); CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); if(lineSpacing == null) {
if(linespacing >= 0) spc.addNewSpcPct().setVal((int)(linespacing*1000)); if (pr.isSetLnSpc()) pr.unsetLnSpc();
else spc.addNewSpcPts().setVal((int)(-linespacing*100)); } else {
pr.setLnSpc(spc); 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 @Override
public double getLineSpacing(){ public Double getLineSpacing(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetLnSpc()){ if(props.isSetLnSpc()){
@ -515,8 +503,8 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
double lnSpc = fetcher.getValue() == null ? 100 : fetcher.getValue(); Double lnSpc = fetcher.getValue();
if(lnSpc > 0) { if (lnSpc != null && lnSpc > 0) {
// check if the percentage value is scaled // check if the percentage value is scaled
CTTextNormalAutofit normAutofit = getParentShape().getTextBodyPr().getNormAutofit(); CTTextNormalAutofit normAutofit = getParentShape().getTextBodyPr().getNormAutofit();
if(normAutofit != null) { if(normAutofit != null) {
@ -528,26 +516,9 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
return lnSpc; return lnSpc;
} }
/** @Override
* Set the amount of vertical white space that will be present before the paragraph. public void setSpaceBefore(Double spaceBefore){
* This space is specified in either percentage or points: if (spaceBefore == null && !_p.isSetPPr()) return;
* <p>
* 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
* </p>
* Examples:
* <pre><code>
* // 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);
* </code></pre>
*
* @param spaceBefore the vertical white space before the paragraph.
*/
public void setSpaceBefore(double spaceBefore){
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
if(spaceBefore >= 0) spc.addNewSpcPct().setVal((int)(spaceBefore*1000)); if(spaceBefore >= 0) spc.addNewSpcPct().setVal((int)(spaceBefore*1000));
@ -555,17 +526,8 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
pr.setSpcBef(spc); pr.setSpcBef(spc);
} }
/** @Override
* The amount of vertical white space before the paragraph public Double getSpaceBefore(){
* This may be specified in two different ways, percentage spacing and font point spacing:
* <p>
* 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
* </p>
*
* @return the vertical white space before the paragraph
*/
public double getSpaceBefore(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetSpcBef()){ if(props.isSetSpcBef()){
@ -580,30 +542,11 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
double spcBef = fetcher.getValue() == null ? 0 : fetcher.getValue(); return fetcher.getValue();
return spcBef;
} }
/** @Override
* Set the amount of vertical white space that will be present after the paragraph. public void setSpaceAfter(Double spaceAfter){
* This space is specified in either percentage or points:
* <p>
* 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
* </p>
* Examples:
* <pre><code>
* // 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);
* </code></pre>
*
* @param spaceAfter the vertical white space after the paragraph.
*/
public void setSpaceAfter(double spaceAfter){
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); CTTextSpacing spc = CTTextSpacing.Factory.newInstance();
if(spaceAfter >= 0) spc.addNewSpcPct().setVal((int)(spaceAfter*1000)); if(spaceAfter >= 0) spc.addNewSpcPct().setVal((int)(spaceAfter*1000));
@ -611,17 +554,8 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
pr.setSpcAft(spc); pr.setSpcAft(spc);
} }
/** @Override
* The amount of vertical white space after the paragraph public Double getSpaceAfter(){
* This may be specified in two different ways, percentage spacing and font point spacing:
* <p>
* 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
* </p>
*
* @return the vertical white space after the paragraph
*/
public double getSpaceAfter(){
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){
public boolean fetch(CTTextParagraphProperties props){ public boolean fetch(CTTextParagraphProperties props){
if(props.isSetSpcAft()){ if(props.isSetSpcAft()){
@ -635,7 +569,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
}; };
fetchParagraphProperty(fetcher); fetchParagraphProperty(fetcher);
return fetcher.getValue() == null ? 0 : fetcher.getValue(); return fetcher.getValue();
} }
/** /**
@ -647,7 +581,6 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
*/ */
public void setLevel(int level){ public void setLevel(int level){
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
pr.setLvl(level); pr.setLvl(level);
} }
@ -657,10 +590,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
*/ */
public int getLevel(){ public int getLevel(){
CTTextParagraphProperties pr = _p.getPPr(); CTTextParagraphProperties pr = _p.getPPr();
if(pr == null) return 0; return (pr == null || !pr.isSetLvl()) ? 0 : pr.getLvl();
return pr.getLvl();
} }
/** /**
@ -721,53 +651,70 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
CTTextParagraphProperties getDefaultMasterStyle(){ /* package */ CTTextParagraphProperties getDefaultMasterStyle(){
CTPlaceholder ph = _shape.getCTPlaceholder(); CTPlaceholder ph = _shape.getCTPlaceholder();
String defaultStyleSelector; String defaultStyleSelector;
if(ph == null) defaultStyleSelector = "otherStyle"; // no placeholder means plain text box switch(ph == null ? -1 : ph.getType().intValue()) {
else { case STPlaceholderType.INT_TITLE:
switch(ph.getType().intValue()){ case STPlaceholderType.INT_CTR_TITLE:
case STPlaceholderType.INT_TITLE: defaultStyleSelector = "titleStyle";
case STPlaceholderType.INT_CTR_TITLE: break;
defaultStyleSelector = "titleStyle"; case -1: // no placeholder means plain text box
break; case STPlaceholderType.INT_FTR:
case STPlaceholderType.INT_FTR: case STPlaceholderType.INT_SLD_NUM:
case STPlaceholderType.INT_SLD_NUM: case STPlaceholderType.INT_DT:
case STPlaceholderType.INT_DT: defaultStyleSelector = "otherStyle";
defaultStyleSelector = "otherStyle"; break;
break; default:
default: defaultStyleSelector = "bodyStyle";
defaultStyleSelector = "bodyStyle"; break;
break;
}
} }
int level = getLevel(); int level = getLevel();
// wind up and find the root master sheet which must be slide master // wind up and find the root master sheet which must be slide master
XSLFSheet masterSheet = _shape.getSheet(); XSLFSheet masterSheet = _shape.getSheet();
while (masterSheet.getMasterSheet() != null){ for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {
masterSheet = (XSLFSheet)masterSheet.getMasterSheet(); masterSheet = m;
} }
XmlObject[] o = masterSheet.getXmlObject().selectPath( String nsDecl =
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " +
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' ";
".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr"); String xpaths[] = {
if (o.length == 1){ nsDecl+".//p:txStyles/p:" + defaultStyleSelector +"/a:lvl" +(level+1)+ "pPr",
return (CTTextParagraphProperties)o[0]; nsDecl+".//p:notesStyle/a:lvl" +(level+1)+ "pPr"
} else { };
o = masterSheet.getXmlObject().selectPath( XmlObject xo = masterSheet.getXmlObject();
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' " + for (String xpath : xpaths) {
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " + XmlObject[] o = xo.selectPath(xpath);
".//p:notesStyle/a:lvl" +(level+1)+ "pPr"); if (o.length == 1) {
if (o.length == 1){
return (CTTextParagraphProperties)o[0]; 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 <T> boolean fetchParagraphProperty(ParagraphPropertyFetcher<T> visitor){ private <T> boolean fetchParagraphProperty(ParagraphPropertyFetcher<T> visitor){
@ -860,9 +807,9 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
@Override @Override
public double getDefaultFontSize() { public Double getDefaultFontSize() {
CTTextCharacterProperties endPr = _p.getEndParaRPr(); CTTextCharacterProperties endPr = _p.getEndParaRPr();
return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100); return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.);
} }
@Override @Override
@ -871,6 +818,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
} }
public BulletStyle getBulletStyle() { public BulletStyle getBulletStyle() {
if (!isBullet()) return null;
return new BulletStyle(){ return new BulletStyle(){
public String getBulletCharacter() { public String getBulletCharacter() {
return XSLFTextParagraph.this.getBulletCharacter(); return XSLFTextParagraph.this.getBulletCharacter();
@ -880,7 +828,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
return XSLFTextParagraph.this.getBulletFont(); return XSLFTextParagraph.this.getBulletFont();
} }
public double getBulletFontSize() { public Double getBulletFontSize() {
return XSLFTextParagraph.this.getBulletFontSize(); return XSLFTextParagraph.this.getBulletFontSize();
} }

View File

@ -17,26 +17,11 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.Color; 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.sl.usermodel.TextRun;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.xslf.model.CharacterPropertyFetcher; import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; import org.openxmlformats.schemas.drawingml.x2006.main.*;
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.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
/** /**
@ -89,28 +74,6 @@ public class XSLFTextRun implements TextRun {
return buf.toString(); 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){ public void setText(String text){
_r.setT(text); _r.setT(text);
} }
@ -175,9 +138,10 @@ public class XSLFTextRun implements TextRun {
} }
/** /**
* @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; double scale = 1;
CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit(); CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit();
if(afit != null) scale = (double)afit.getFontScale() / 100000; if(afit != null) scale = (double)afit.getFontScale() / 100000;
@ -192,7 +156,7 @@ public class XSLFTextRun implements TextRun {
} }
}; };
fetchCharacterProperty(fetcher); 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 TextRun {
return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this); return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this);
} }
private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){ private boolean fetchCharacterProperty(CharacterPropertyFetcher<?> fetcher){
boolean ok = false; boolean ok = false;
if(_r.isSetRPr()) ok = fetcher.fetch(getRPr()); if(_r.isSetRPr()) ok = fetcher.fetch(getRPr());

View File

@ -125,7 +125,7 @@ public class TestXSLFAutoShape {
p.setIndent(2.0); p.setIndent(2.0);
assertEquals(2.0, p.getIndent(), 0); assertEquals(2.0, p.getIndent(), 0);
assertTrue(p.getXmlObject().getPPr().isSetIndent()); assertTrue(p.getXmlObject().getPPr().isSetIndent());
p.setIndent(-1); p.setIndent(-1d);
assertEquals(0.0, p.getIndent(), 0); assertEquals(0.0, p.getIndent(), 0);
assertFalse(p.getXmlObject().getPPr().isSetIndent()); assertFalse(p.getXmlObject().getPPr().isSetIndent());
p.setIndent(10.0); p.setIndent(10.0);
@ -149,44 +149,44 @@ public class TestXSLFAutoShape {
assertFalse(p.getXmlObject().getPPr().isSetSpcAft()); assertFalse(p.getXmlObject().getPPr().isSetSpcAft());
p.setSpaceAfter(200); p.setSpaceAfter(200d);
assertEquals(200000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); assertEquals(200000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts());
p.setSpaceAfter(100); p.setSpaceAfter(100d);
assertEquals(100000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal()); assertEquals(100000, p.getXmlObject().getPPr().getSpcAft().getSpcPct().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPts());
p.setSpaceAfter(-20); p.setSpaceAfter(-20d);
assertEquals(2000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); assertEquals(2000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct());
p.setSpaceAfter(-10); p.setSpaceAfter(-10d);
assertEquals(1000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal()); assertEquals(1000, p.getXmlObject().getPPr().getSpcAft().getSpcPts().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().getSpcAft().isSetSpcPct());
assertFalse(p.getXmlObject().getPPr().isSetSpcBef()); assertFalse(p.getXmlObject().getPPr().isSetSpcBef());
p.setSpaceBefore(200); p.setSpaceBefore(200d);
assertEquals(200000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); assertEquals(200000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts());
p.setSpaceBefore(100); p.setSpaceBefore(100d);
assertEquals(100000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal()); assertEquals(100000, p.getXmlObject().getPPr().getSpcBef().getSpcPct().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPts());
p.setSpaceBefore(-20); p.setSpaceBefore(-20d);
assertEquals(2000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); assertEquals(2000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct());
p.setSpaceBefore(-10); p.setSpaceBefore(-10d);
assertEquals(1000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal()); assertEquals(1000, p.getXmlObject().getPPr().getSpcBef().getSpcPts().getVal());
assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().getSpcBef().isSetSpcPct());
assertFalse(p.getXmlObject().getPPr().isSetLnSpc()); assertFalse(p.getXmlObject().getPPr().isSetLnSpc());
p.setLineSpacing(200); p.setLineSpacing(200d);
assertEquals(200000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); assertEquals(200000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal());
assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts());
p.setLineSpacing(100); p.setLineSpacing(100d);
assertEquals(100000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal()); assertEquals(100000, p.getXmlObject().getPPr().getLnSpc().getSpcPct().getVal());
assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPts());
p.setLineSpacing(-20); p.setLineSpacing(-20d);
assertEquals(2000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); assertEquals(2000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal());
assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct());
p.setLineSpacing(-10); p.setLineSpacing(-10d);
assertEquals(1000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal()); assertEquals(1000, p.getXmlObject().getPPr().getLnSpc().getSpcPts().getVal());
assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct()); assertFalse(p.getXmlObject().getPPr().getLnSpc().isSetSpcPct());

View File

@ -92,7 +92,7 @@ public class TestXSLFTextParagraph {
assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0);
assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);
p.setLeftMargin(36); // 0.5" p.setLeftMargin(36d); // 0.5"
leftMargin = p.getLeftMargin(); leftMargin = p.getLeftMargin();
assertEquals(36.0, leftMargin, 0); assertEquals(36.0, leftMargin, 0);
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;

View File

@ -21,12 +21,13 @@ package org.apache.poi.hslf.model.textproperties;
* Definition for the font alignment property. * Definition for the font alignment property.
*/ */
public class FontAlignmentProp extends TextProp { public class FontAlignmentProp extends TextProp {
public static final String NAME = "fontAlign";
public static final int BASELINE = 0; public static final int BASELINE = 0;
public static final int TOP = 1; public static final int TOP = 1;
public static final int CENTER = 2; public static final int CENTER = 2;
public static final int BOTTOM = 3; public static final int BOTTOM = 3;
public FontAlignmentProp() { public FontAlignmentProp() {
super(2, 0x10000, "fontAlign"); super(2, 0x10000, NAME);
} }
} }

View File

@ -31,47 +31,10 @@ import org.apache.poi.util.LittleEndian;
* properties, and the indent level if required. * properties, and the indent level if required.
*/ */
public class TextPropCollection { 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 */ /** All the different kinds of paragraph properties we might handle */
public static final TextProp[] paragraphTextPropTypes = { public static final TextProp[] paragraphTextPropTypes = {
// TextProp order is according to 2.9.20 TextPFException, // TextProp order is according to 2.9.20 TextPFException,
// bitmask order can be different // 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 ParagraphFlagsTextProp(),
new TextProp(2, 0x80, "bullet.char"), new TextProp(2, 0x80, "bullet.char"),
new TextProp(2, 0x10, "bullet.font"), new TextProp(2, 0x10, "bullet.font"),
@ -95,24 +58,9 @@ public class TextPropCollection {
new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size
// 0xFC000000 MUST be zero and MUST be ignored // 0xFC000000 MUST be zero and MUST be ignored
}; };
/** All the different kinds of character properties we might handle */ /** All the different kinds of character properties we might handle */
public static final TextProp[] characterTextPropTypes = new TextProp[] { 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, 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, 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. new TextProp(0, 0x2000000, "cs.font.index"), // A bit that specifies whether the csFontRef field of the TextCFException10 structure that contains this CFMasks exists.
@ -167,6 +115,19 @@ public class TextPropCollection {
return null; return null;
} }
public TextProp removeByName(String name) {
Iterator<TextProp> 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 */ /** Add the TextProp with this name to the list */
public TextProp addWithName(String name) { public TextProp addWithName(String name) {
// Find the base TextProp to base on // Find the base TextProp to base on
@ -192,6 +153,10 @@ public class TextPropCollection {
return textProp; return textProp;
} }
public TextPropType getTextPropType() {
return textPropType;
}
private TextProp[] getPotentialProperties() { private TextProp[] getPotentialProperties() {
return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes; return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes;
} }

View File

@ -17,6 +17,7 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import org.apache.poi.hslf.model.PPFont;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import java.io.*; import java.io.*;
@ -75,9 +76,9 @@ public final class FontCollection extends RecordContainer {
*/ */
public int addFont(String name) { public int addFont(String name) {
int idx = getFontIndex(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) { public int addFont(String name, int charset, int flags, int type, int pitch) {

View File

@ -76,45 +76,31 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
* This is the "workhorse" which returns the default style attrubutes. * This is the "workhorse" which returns the default style attrubutes.
*/ */
public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) { public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
if (_txmaster.length <= txtype) return null;
TxMasterStyleAtom t = _txmaster[txtype];
List<TextPropCollection> styles = isCharacter ? t.getCharacterStyles() : t.getParagraphStyles();
TextProp prop = null; TextProp prop = null;
for (int i = level; i >= 0; i--) { for (int i = Math.min(level, styles.size()-1); prop == null && i >= 0; i--) {
List<TextPropCollection> styles = prop = styles.get(i).findByName(name);
isCharacter ? _txmaster[txtype].getCharacterStyles() : _txmaster[txtype].getParagraphStyles();
if (i < styles.size()) prop = styles.get(i).findByName(name);
if (prop != null) break;
} }
if (prop == null) {
if(isCharacter) { if (prop != null) return prop;
switch (txtype) {
case TextHeaderAtom.CENTRE_BODY_TYPE: switch (txtype) {
case TextHeaderAtom.HALF_BODY_TYPE: case TextHeaderAtom.CENTRE_BODY_TYPE:
case TextHeaderAtom.QUARTER_BODY_TYPE: case TextHeaderAtom.HALF_BODY_TYPE:
txtype = TextHeaderAtom.BODY_TYPE; case TextHeaderAtom.QUARTER_BODY_TYPE:
break; txtype = TextHeaderAtom.BODY_TYPE;
case TextHeaderAtom.CENTER_TITLE_TYPE: break;
txtype = TextHeaderAtom.TITLE_TYPE; case TextHeaderAtom.CENTER_TITLE_TYPE:
break; txtype = TextHeaderAtom.TITLE_TYPE;
default: break;
return null; 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);
} }
return prop;
return getStyleAttribute(txtype, level, name, isCharacter);
} }
/** /**

View File

@ -17,7 +17,8 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.fetchOrAddTextProp; import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.setPropVal;
import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.getPropVal;
import java.awt.Color; import java.awt.Color;
@ -132,29 +133,8 @@ public final class HSLFTextRun implements TextRun {
* it if required. * it if required.
*/ */
private void setCharFlagsTextPropVal(int index, boolean value) { private void setCharFlagsTextPropVal(int index, boolean value) {
if(getFlag(index) != value) setFlag(index, value); // TODO: check if paragraph/chars can be handled the same ...
} if (getFlag(index) != value) setFlag(index, value);
/**
* Fetch the value of the given Character related TextProp.
* Returns -1 if that TextProp isn't present.
* If the TextProp isn't present, the value from the appropriate
* Master Sheet will apply.
*/
private int getCharTextPropVal(String propName) {
TextProp prop = null;
if (characterStyle != null){
prop = characterStyle.findByName(propName);
}
if (prop == null){
HSLFSheet sheet = parentParagraph.getSheet();
int txtype = parentParagraph.getRunType();
HSLFMasterSheet master = sheet.getMasterSheet();
if (master != null)
prop = master.getStyleAttribute(txtype, parentParagraph.getIndentLevel(), propName, true);
}
return prop == null ? -1 : prop.getValue();
} }
/** /**
@ -163,8 +143,7 @@ public final class HSLFTextRun implements TextRun {
* @param val The value to set for the TextProp * @param val The value to set for the TextProp
*/ */
public void setCharTextPropVal(String propName, int val) { public void setCharTextPropVal(String propName, int val) {
TextProp tp = fetchOrAddTextProp(characterStyle, propName); setPropVal(characterStyle, propName, val);
tp.setValue(val);
} }
@ -260,8 +239,8 @@ public final class HSLFTextRun implements TextRun {
* @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript * @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript
*/ */
public int getSuperscript() { public int getSuperscript() {
int val = getCharTextPropVal("superscript"); TextProp tp = getPropVal(characterStyle, "superscript", parentParagraph);
return val == -1 ? 0 : val; return tp == null ? 0 : tp.getValue();
} }
/** /**
@ -270,14 +249,15 @@ public final class HSLFTextRun implements TextRun {
* @param val the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript * @param val the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript
*/ */
public void setSuperscript(int val) { public void setSuperscript(int val) {
setCharTextPropVal("superscript", val); setPropVal(characterStyle, "superscript", val);
} }
/** /**
* Gets the font size * Gets the font size
*/ */
public double getFontSize() { public Double getFontSize() {
return getCharTextPropVal("font.size"); TextProp tp = getPropVal(characterStyle, "font.size", parentParagraph);
return tp == null ? null : (double)tp.getValue();
} }
@ -292,7 +272,8 @@ public final class HSLFTextRun implements TextRun {
* Gets the font index * Gets the font index
*/ */
public int getFontIndex() { public int getFontIndex() {
return getCharTextPropVal("font.index"); TextProp tp = getPropVal(characterStyle, "font.index", parentParagraph);
return tp == null ? -1 : tp.getValue();
} }
/** /**
@ -329,9 +310,9 @@ public final class HSLFTextRun implements TextRun {
if (sheet == null || slideShow == null) { if (sheet == null || slideShow == null) {
return _fontFamily; return _fontFamily;
} }
int fontIdx = getCharTextPropVal("font.index"); TextProp tp = getPropVal(characterStyle, "font.index", parentParagraph);
if(fontIdx == -1) { return null; } if (tp == null) { return null; }
return slideShow.getFontCollection().getFontWithId(fontIdx); return slideShow.getFontCollection().getFontWithId(tp.getValue());
} }
/** /**
@ -339,7 +320,9 @@ public final class HSLFTextRun implements TextRun {
* @see java.awt.Color * @see java.awt.Color
*/ */
public Color getFontColor() { public Color getFontColor() {
int rgb = getCharTextPropVal("font.color"); TextProp tp = getPropVal(characterStyle, "font.color", parentParagraph);
if (tp == null) return null;
int rgb = tp.getValue();
int cidx = rgb >> 24; int cidx = rgb >> 24;
if (rgb % 0x1000000 == 0){ if (rgb % 0x1000000 == 0){
@ -370,7 +353,7 @@ public final class HSLFTextRun implements TextRun {
} }
protected void setFlag(int index, boolean value) { protected void setFlag(int index, boolean value) {
BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(characterStyle, CharFlagsTextProp.NAME); BitMaskTextProp prop = (BitMaskTextProp)characterStyle.addWithName(CharFlagsTextProp.NAME);
prop.setSubValue(value, index); prop.setSubValue(value, index);
} }

View File

@ -55,12 +55,21 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
double rightInset = insets.right; double rightInset = insets.right;
double penY = y; double penY = y;
double leftMargin = paragraph.getLeftMargin();
boolean firstLine = true; boolean firstLine = true;
double indent = paragraph.getIndent(); Double leftMargin = paragraph.getLeftMargin();
Double indent = paragraph.getIndent();
if (leftMargin == null) {
leftMargin = (indent != null) ? -indent : 0;
}
if (indent == null) {
indent = (leftMargin != null) ? -leftMargin : 0;
}
//The vertical line spacing //The vertical line spacing
double spacing = paragraph.getLineSpacing(); Double spacing = paragraph.getLineSpacing();
if (spacing == null) spacing = 100d;
for(DrawTextFragment line : lines){ for(DrawTextFragment line : lines){
double penX = x + leftMargin; double penX = x + leftMargin;
@ -77,7 +86,7 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
bullet.setPosition(penX + indent, penY); bullet.setPosition(penX + indent, penY);
} else if(indent > 0){ } else if(indent > 0){
// a positive value means the "First Line" indentation: // a positive value means the "First Line" indentation:
// the first line is indented and other lines start at the bullet ofset // the first line is indented and other lines start at the bullet offset
bullet.setPosition(penX, penY); bullet.setPosition(penX, penY);
penX += indent; penX += indent;
} else { } else {
@ -96,7 +105,9 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape()); Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape());
switch (paragraph.getTextAlign()) { TextAlign ta = paragraph.getTextAlign();
if (ta == null) ta = TextAlign.LEFT;
switch (ta) {
case CENTER: case CENTER:
penX += (anchor.getWidth() - leftMargin - line.getWidth() - leftInset - rightInset) / 2; penX += (anchor.getWidth() - leftMargin - line.getWidth() - leftInset - rightInset) / 2;
break; break;
@ -219,9 +230,10 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
if (buColor == null) buColor = (Color)firstLineAttr.getAttribute(TextAttribute.FOREGROUND); if (buColor == null) buColor = (Color)firstLineAttr.getAttribute(TextAttribute.FOREGROUND);
float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE); float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE);
float buSz = (float)bulletStyle.getBulletFontSize(); Double buSz = bulletStyle.getBulletFontSize();
if(buSz > 0) fontSize *= buSz* 0.01; if (buSz == null) buSz = 100d;
else fontSize = -buSz; if (buSz > 0) fontSize *= buSz* 0.01;
else fontSize = (float)-buSz;
AttributedString str = new AttributedString(buCharacter); AttributedString str = new AttributedString(buCharacter);
@ -237,10 +249,13 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
protected String getRenderableText(TextRun tr) { protected String getRenderableText(TextRun tr) {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
TextCap cap = tr.getTextCap(); TextCap cap = tr.getTextCap();
String tabs = null;
for (char c : tr.getRawText().toCharArray()) { for (char c : tr.getRawText().toCharArray()) {
if(c == '\t') { if(c == '\t') {
// TODO: finish support for tabs if (tabs == null) {
buf.append(" "); tabs = tab2space(tr);
}
buf.append(tabs);
continue; continue;
} }
@ -256,6 +271,34 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
return buf.toString(); return buf.toString();
} }
/**
* Replace a tab with the effective number of white spaces.
*/
private String tab2space(TextRun tr) {
AttributedString string = new AttributedString(" ");
String typeFace = tr.getFontFamily();
if (typeFace == null) typeFace = "Lucida Sans";
string.addAttribute(TextAttribute.FAMILY, typeFace);
Double fs = tr.getFontSize();
if (fs == null) fs = 12d;
string.addAttribute(TextAttribute.SIZE, fs.floatValue());
TextLayout l = new TextLayout(string.getIterator(), new FontRenderContext(null, true, true));
double wspace = l.getAdvance();
Double tabSz = paragraph.getDefaultTabSize();
if (tabSz == null) tabSz = wspace*4;
int numSpaces = (int)Math.ceil(tabSz / wspace);
StringBuilder buf = new StringBuilder();
for(int i = 0; i < numSpaces; i++) {
buf.append(' ');
}
return buf.toString();
}
/** /**
* Returns wrapping width to break lines in this paragraph * Returns wrapping width to break lines in this paragraph
* *
@ -271,8 +314,14 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape()); Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape());
double leftMargin = paragraph.getLeftMargin(); Double leftMargin = paragraph.getLeftMargin();
double indent = paragraph.getIndent(); Double indent = paragraph.getIndent();
if (leftMargin == null) {
leftMargin = (indent != null) ? -indent : 0;
}
if (indent == null) {
indent = (leftMargin != null) ? -leftMargin : 0;
}
double width; double width;
TextShape<? extends TextParagraph<T>> ts = paragraph.getParentShape(); TextShape<? extends TextParagraph<T>> ts = paragraph.getParentShape();
@ -323,7 +372,9 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
text.append(runText); text.append(runText);
int endIndex = text.length(); int endIndex = text.length();
attList.add(new AttributedStringData(TextAttribute.FOREGROUND, run.getFontColor(), beginIndex, endIndex)); Color fgColor = run.getFontColor();
if (fgColor == null) fgColor = Color.BLACK;
attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgColor, beginIndex, endIndex));
// user can pass an custom object to convert fonts // user can pass an custom object to convert fonts
String fontFamily = run.getFontFamily(); String fontFamily = run.getFontFamily();
@ -335,10 +386,14 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
if(fontHandler != null) { if(fontHandler != null) {
fontFamily = fontHandler.getRendererableFont(fontFamily, run.getPitchAndFamily()); fontFamily = fontHandler.getRendererableFont(fontFamily, run.getPitchAndFamily());
} }
if (fontFamily == null) {
fontFamily = paragraph.getDefaultFontFamily();
}
attList.add(new AttributedStringData(TextAttribute.FAMILY, fontFamily, beginIndex, endIndex)); attList.add(new AttributedStringData(TextAttribute.FAMILY, fontFamily, beginIndex, endIndex));
float fontSz = (float)run.getFontSize(); Double fontSz = run.getFontSize();
attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz, beginIndex, endIndex)); if (fontSz == null) fontSz = paragraph.getDefaultFontSize();
attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), beginIndex, endIndex));
if(run.isBold()) { if(run.isBold()) {
attList.add(new AttributedStringData(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, beginIndex, endIndex)); attList.add(new AttributedStringData(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, beginIndex, endIndex));
@ -364,9 +419,9 @@ public class DrawTextParagraph<T extends TextRun> implements Drawable {
// ensure that the paragraph contains at least one character // ensure that the paragraph contains at least one character
// We need this trick to correctly measure text // We need this trick to correctly measure text
if (text.length() == 0) { if (text.length() == 0) {
float fontSz = (float)paragraph.getDefaultFontSize(); Double fontSz = paragraph.getDefaultFontSize();
text.append(" "); text.append(" ");
attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz, 0, 1)); attList.add(new AttributedStringData(TextAttribute.SIZE, fontSz.floatValue(), 0, 1));
} }
AttributedString string = new AttributedString(text.toString()); AttributedString string = new AttributedString(text.toString());

View File

@ -95,7 +95,8 @@ public class DrawTextShape<T extends TextShape<? extends TextParagraph<? extends
if (!isFirstLine) { if (!isFirstLine) {
// the amount of vertical white space before the paragraph // the amount of vertical white space before the paragraph
double spaceBefore = p.getSpaceBefore(); Double spaceBefore = p.getSpaceBefore();
if (spaceBefore == null) spaceBefore = 0d;
if(spaceBefore > 0) { if(spaceBefore > 0) {
// positive value means percentage spacing of the height of the first line, e.g. // positive value means percentage spacing of the height of the first line, e.g.
// the higher the first line, the bigger the space before the paragraph // the higher the first line, the bigger the space before the paragraph
@ -112,7 +113,8 @@ public class DrawTextShape<T extends TextShape<? extends TextParagraph<? extends
y += dp.getY(); y += dp.getY();
if (paragraphs.hasNext()) { if (paragraphs.hasNext()) {
double spaceAfter = p.getSpaceAfter(); Double spaceAfter = p.getSpaceAfter();
if (spaceAfter == null) spaceAfter = 0d;
if(spaceAfter > 0) { if(spaceAfter > 0) {
// positive value means percentage spacing of the height of the last line, e.g. // positive value means percentage spacing of the height of the last line, e.g.
// the higher the last line, the bigger the space after the paragraph // the higher the last line, the bigger the space after the paragraph

View File

@ -104,7 +104,15 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
public interface BulletStyle { public interface BulletStyle {
String getBulletCharacter(); String getBulletCharacter();
String getBulletFont(); String getBulletFont();
double getBulletFontSize();
/**
* The bullet point font size
* If bulletFontSize >= 0, then space is a percentage of normal line height.
* If bulletFontSize < 0, the absolute value in points
*
* @return the bullet point font size
*/
Double getBulletFontSize();
Color getBulletFontColor(); Color getBulletFontColor();
} }
@ -116,9 +124,30 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
* If spaceBefore < 0, the absolute value in points * If spaceBefore < 0, the absolute value in points
* </p> * </p>
* *
* @return the vertical white space before the paragraph * @return the vertical white space before the paragraph, or null if unset
*/ */
double getSpaceBefore(); Double getSpaceBefore();
/**
* Set the amount of vertical white space that will be present before the paragraph.
* This space is specified in either percentage or points:
* <p>
* 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
* </p>
* Examples:
* <pre><code>
* // 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);
* </code></pre>
*
* @param spaceBefore the vertical white space before the paragraph, null to unset
*/
void setSpaceBefore(Double spaceBefore);
/** /**
* The amount of vertical white space after the paragraph * The amount of vertical white space after the paragraph
@ -128,40 +157,74 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
* If spaceBefore < 0, the absolute value of linespacing is the spacing in points * If spaceBefore < 0, the absolute value of linespacing is the spacing in points
* </p> * </p>
* *
* @return the vertical white space after the paragraph * @return the vertical white space after the paragraph or null, if unset
*/ */
double getSpaceAfter(); Double getSpaceAfter();
/** /**
* @return the left margin (in points) of the paragraph * Set the amount of vertical white space that will be present after the paragraph.
* This space is specified in either percentage or points:
* <p>
* 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
* </p>
* Examples:
* <pre><code>
* // 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);
* </code></pre>
*
* @param spaceAfter the vertical white space after the paragraph, null to unset
*/ */
double getLeftMargin(); public void setSpaceAfter(Double spaceAfter);
/** /**
* @param leftMargin the left margin (in points) * @return the left margin (in points) of the paragraph or null, if unset
*/ */
void setLeftMargin(double leftMargin); Double getLeftMargin();
/**
* 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 leftMargin the left margin (in points) or null to unset
*/
void setLeftMargin(Double leftMargin);
/** /**
* @return the right margin (in points) of the paragraph * 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.
*
* The right margin is not support and therefore ignored by the HSLF implementation.
*
* @return the right margin (in points) of the paragraph or null, if unset
*/ */
double getRightMargin(); Double getRightMargin();
/** /**
* @param rightMargin the right margin (in points) of the paragraph * @param rightMargin the right margin (in points) of the paragraph
*/ */
void setRightMargin(double rightMargin); void setRightMargin(Double rightMargin);
/** /**
* @return the indent (in points) applied to the first line of text in the paragraph. * @return the indent (in points) applied to the first line of text in the paragraph.
* or null, if unset
*/ */
double getIndent(); Double getIndent();
/** /**
* Specifies the indent size that will be applied to the first line of text in the paragraph.
*
* @param indent the indent (in points) applied to the first line of text in the paragraph * @param indent the indent (in points) applied to the first line of text in the paragraph
*/ */
void setIndent(double indent); void setIndent(Double indent);
/** /**
* Returns the vertical line spacing that is to be used within a paragraph. * Returns the vertical line spacing that is to be used within a paragraph.
@ -171,9 +234,9 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
* If linespacing < 0, the absolute value of linespacing is the spacing in points * If linespacing < 0, the absolute value of linespacing is the spacing in points
* </p> * </p>
* *
* @return the vertical line spacing. * @return the vertical line spacing or null, if unset
*/ */
double getLineSpacing(); Double getLineSpacing();
/** /**
* This element specifies the vertical line spacing that is to be used within a paragraph. * This element specifies the vertical line spacing that is to be used within a paragraph.
@ -196,14 +259,14 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
* *
* @param linespacing the vertical line spacing * @param linespacing the vertical line spacing
*/ */
void setLineSpacing(double lineSpacing); void setLineSpacing(Double lineSpacing);
String getDefaultFontFamily(); String getDefaultFontFamily();
/** /**
* @return the default font size, in case its not set in the textrun * @return the default font size, in case its not set in the textrun or null, if unset
*/ */
double getDefaultFontSize(); Double getDefaultFontSize();
/** /**
* Returns the alignment that is applied to the paragraph. * Returns the alignment that is applied to the paragraph.
@ -217,8 +280,10 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
/** /**
* Returns the font alignment that is applied to the paragraph. * Returns the font alignment that is applied to the paragraph.
* *
* If this attribute is omitted, then a value of auto (~ left) is implied. * If this attribute is omitted, then null is return,
* @return ??? alignment that is applied to the paragraph * user code can imply the a value of {@link FontAlign#AUTO}
*
* @return alignment that is applied to the paragraph
*/ */
FontAlign getFontAlign(); FontAlign getFontAlign();
@ -227,5 +292,11 @@ public interface TextParagraph<T extends TextRun> extends Iterable<T> {
*/ */
BulletStyle getBulletStyle(); BulletStyle getBulletStyle();
/**
* @return the default size for a tab character within this paragraph in points, null if unset
*/
Double getDefaultTabSize();
TextShape<? extends TextParagraph<T>> getParentShape(); TextShape<? extends TextParagraph<T>> getParentShape();
} }

View File

@ -21,8 +21,6 @@ import java.awt.Color;
/** /**
* Some text. * Some text.
*
* TODO - decide on how we do rich text stuff
*/ */
public interface TextRun { public interface TextRun {
enum TextCap { enum TextCap {
@ -31,13 +29,13 @@ public interface TextRun {
ALL ALL
} }
public String getRawText(); String getRawText();
public void setText(String text); void setText(String text);
TextCap getTextCap(); TextCap getTextCap();
Color getFontColor(); Color getFontColor();
double getFontSize(); Double getFontSize();
String getFontFamily(); String getFontFamily();
boolean isBold(); boolean isBold();

View File

@ -22,8 +22,7 @@ import static org.junit.Assert.*;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@ -35,7 +34,6 @@ import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.util.JvmBugs; import org.apache.poi.util.JvmBugs;
import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
/** /**
@ -142,29 +140,43 @@ public final class TestPicture {
@Test @Test
// @Ignore("Just for visual validation - antialiasing is different on various systems") // @Ignore("Just for visual validation - antialiasing is different on various systems")
public void bug54541() throws Exception { public void bug54541() throws Exception {
String file = new String[]{ String files[] = {
"54542_cropped_bitmap.pptx", // "sample_pptx_grouping_issues.pptx",
"54541_cropped_bitmap.ppt", // "54542_cropped_bitmap.pptx",
"54541_cropped_bitmap2.ppt", // "54541_cropped_bitmap.ppt",
"sample_pptx_grouping_issues.pptx" // "54541_cropped_bitmap2.ppt",
}[3]; // "alterman_security.ppt",
InputStream is = _slTests.openResourceAsStream(file); "alterman_security2.pptx",
SlideShow ss = file.endsWith("pptx") ? new XMLSlideShow(is) : new HSLFSlideShow(is); };
is.close();
boolean debugOut = false; BitSet pages = new BitSet();
Dimension pg = ss.getPageSize(); pages.set(2);
int i=1;
for(Slide<?,?,?> slide : ss.getSlides()) { for (String file : files) {
if (debugOut) { InputStream is = _slTests.openResourceAsStream(file);
DummyGraphics2d graphics = new DummyGraphics2d(); SlideShow ss = file.endsWith("pptx") ? new XMLSlideShow(is) : new HSLFSlideShow(is);
slide.draw(graphics); is.close();
} else {
BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB); boolean debugOut = false;
Graphics2D graphics = img.createGraphics(); Dimension pg = ss.getPageSize();
fixFonts(graphics); for (Slide<?,?,?> slide : ss.getSlides()) {
slide.draw(graphics); int slideNo = slide.getSlideNumber();
ImageIO.write(img, "PNG", new File("test"+(i++)+"hslf.png")); if (!pages.get(slideNo-1)) {
if (pages.nextSetBit(slideNo-1) == -1) break; else continue;
}
if (debugOut) {
DummyGraphics2d graphics = new DummyGraphics2d();
slide.draw(graphics);
} else {
BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = img.createGraphics();
fixFonts(graphics);
slide.draw(graphics);
graphics.setColor(Color.BLACK);
graphics.setStroke(new BasicStroke(1));
graphics.drawRect(0, 0, (int)pg.getWidth()-1, (int)pg.getHeight()-1);
ImageIO.write(img, "PNG", new File(file.replaceFirst(".pptx?", "-")+slideNo+".png"));
}
} }
} }
} }

View File

@ -470,7 +470,7 @@ public final class TestRichTextRun {
assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(1))); assertEquals(expected, HSLFTextParagraph.getRawText(txt.get(1)));
assertEquals(4, txt.get(1).size()); assertEquals(4, txt.get(1).size());
rt = txt.get(1).get(0); rt = txt.get(1).get(0);
assertEquals('\u2022', rt.getBulletChar()); assertEquals('\u2022', (char)rt.getBulletChar());
assertTrue(rt.isBullet()); assertTrue(rt.isBullet());
@ -486,7 +486,7 @@ public final class TestRichTextRun {
assertEquals(4, txt.get(0).size()); assertEquals(4, txt.get(0).size());
rt = txt.get(0).get(0); rt = txt.get(0).get(0);
assertTrue(rt.isBullet()); assertTrue(rt.isBullet());
assertEquals('\u2022', rt.getBulletChar()); assertEquals('\u2022', (char)rt.getBulletChar());
expected = expected =
"I\u2019m a text box with user-defined\r" + "I\u2019m a text box with user-defined\r" +
@ -495,7 +495,7 @@ public final class TestRichTextRun {
assertEquals(2, txt.get(1).size()); assertEquals(2, txt.get(1).size());
rt = txt.get(1).get(0); rt = txt.get(1).get(0);
assertTrue(rt.isBullet()); assertTrue(rt.isBullet());
assertEquals('\u263A', rt.getBulletChar()); assertEquals('\u263A', (char)rt.getBulletChar());
} }
@Test @Test
@ -513,8 +513,8 @@ public final class TestRichTextRun {
HSLFTextRun tr = rt.getTextRuns().get(0); HSLFTextRun tr = rt.getTextRuns().get(0);
tr.setFontSize(42); tr.setFontSize(42);
rt.setBullet(true); rt.setBullet(true);
rt.setLeftMargin(50); rt.setLeftMargin(50d);
rt.setIndent(0); rt.setIndent(0d);
rt.setBulletChar('\u263A'); rt.setBulletChar('\u263A');
slide.addShape(shape); slide.addShape(shape);
@ -522,7 +522,7 @@ public final class TestRichTextRun {
assertEquals(true, rt.isBullet()); assertEquals(true, rt.isBullet());
assertEquals(50.0, rt.getLeftMargin(), 0); assertEquals(50.0, rt.getLeftMargin(), 0);
assertEquals(0, rt.getIndent(), 0); assertEquals(0, rt.getIndent(), 0);
assertEquals('\u263A', rt.getBulletChar()); assertEquals('\u263A', (char)rt.getBulletChar());
shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300)); shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300));
slide.addShape(shape); slide.addShape(shape);
@ -541,7 +541,7 @@ public final class TestRichTextRun {
assertEquals(true, rt.isBullet()); assertEquals(true, rt.isBullet());
assertEquals(50.0, rt.getLeftMargin(), 0); assertEquals(50.0, rt.getLeftMargin(), 0);
assertEquals(0, rt.getIndent(), 0); assertEquals(0, rt.getIndent(), 0);
assertEquals('\u263A', rt.getBulletChar()); assertEquals('\u263A', (char)rt.getBulletChar());
} }
@Test @Test

View File

@ -556,7 +556,7 @@ public final class TestTextRun {
int i=0; int i=0;
for (List<HSLFTextParagraph> textParas : slide.getTextParagraphs()) { for (List<HSLFTextParagraph> textParas : slide.getTextParagraphs()) {
assertEquals("Arial", textParas.get(0).getTextRuns().get(0).getFontFamily()); assertEquals("Arial", textParas.get(0).getTextRuns().get(0).getFontFamily());
assertEquals(sizes[i++], (int)textParas.get(0).getTextRuns().get(0).getFontSize()); assertEquals(sizes[i++], textParas.get(0).getTextRuns().get(0).getFontSize().intValue());
} }
} }

Binary file not shown.