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:
parent
2170a52383
commit
f97d6f6c34
@ -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" +
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,16 +651,15 @@ 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 {
|
|
||||||
switch(ph.getType().intValue()){
|
|
||||||
case STPlaceholderType.INT_TITLE:
|
case STPlaceholderType.INT_TITLE:
|
||||||
case STPlaceholderType.INT_CTR_TITLE:
|
case STPlaceholderType.INT_CTR_TITLE:
|
||||||
defaultStyleSelector = "titleStyle";
|
defaultStyleSelector = "titleStyle";
|
||||||
break;
|
break;
|
||||||
|
case -1: // no placeholder means plain text box
|
||||||
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:
|
||||||
@ -740,34 +669,52 @@ public class XSLFTextParagraph implements TextParagraph<XSLFTextRun> {
|
|||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -76,16 +76,17 @@ 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) {
|
switch (txtype) {
|
||||||
case TextHeaderAtom.CENTRE_BODY_TYPE:
|
case TextHeaderAtom.CENTRE_BODY_TYPE:
|
||||||
case TextHeaderAtom.HALF_BODY_TYPE:
|
case TextHeaderAtom.HALF_BODY_TYPE:
|
||||||
@ -98,23 +99,8 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
switch (txtype) {
|
return getStyleAttribute(txtype, level, name, isCharacter);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,11 +44,10 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
/**
|
/**
|
||||||
* How to align the text
|
* How to align the text
|
||||||
*/
|
*/
|
||||||
/* package */ static final int AlignLeft = 0;
|
/* package */static final int AlignLeft = 0;
|
||||||
/* package */ static final int AlignCenter = 1;
|
/* package */static final int AlignCenter = 1;
|
||||||
/* package */ static final int AlignRight = 2;
|
/* package */static final int AlignRight = 2;
|
||||||
/* package */ static final int AlignJustify = 3;
|
/* package */static final int AlignJustify = 3;
|
||||||
|
|
||||||
|
|
||||||
// Note: These fields are protected to help with unit testing
|
// Note: These fields are protected to help with unit testing
|
||||||
// Other classes shouldn't really go playing with them!
|
// Other classes shouldn't really go playing with them!
|
||||||
@ -58,7 +57,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
private final TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
|
private final TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
|
||||||
|
|
||||||
protected TextRulerAtom _ruler;
|
protected TextRulerAtom _ruler;
|
||||||
protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();
|
protected final List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();
|
||||||
protected HSLFTextShape _parentShape;
|
protected HSLFTextShape _parentShape;
|
||||||
private HSLFSheet _sheet;
|
private HSLFSheet _sheet;
|
||||||
private int shapeId;
|
private int shapeId;
|
||||||
@ -87,7 +86,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
_charAtom = tca;
|
_charAtom = tca;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ HSLFTextParagraph(HSLFTextParagraph other) {
|
/* package */HSLFTextParagraph(HSLFTextParagraph other) {
|
||||||
_headerAtom = other._headerAtom;
|
_headerAtom = other._headerAtom;
|
||||||
_byteAtom = other._byteAtom;
|
_byteAtom = other._byteAtom;
|
||||||
_charAtom = other._charAtom;
|
_charAtom = other._charAtom;
|
||||||
@ -122,37 +121,37 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
* Supply the Sheet we belong to, which might have an assigned SlideShow
|
* Supply the Sheet we belong to, which might have an assigned SlideShow
|
||||||
* Also passes it on to our child RichTextRuns
|
* Also passes it on to our child RichTextRuns
|
||||||
*/
|
*/
|
||||||
public void supplySheet(HSLFSheet sheet){
|
public void supplySheet(HSLFSheet sheet) {
|
||||||
this._sheet = sheet;
|
this._sheet = sheet;
|
||||||
|
|
||||||
if (_runs == null) return;
|
if (_runs == null) return;
|
||||||
for(HSLFTextRun rt : _runs) {
|
for (HSLFTextRun rt : _runs) {
|
||||||
rt.updateSheet();
|
rt.updateSheet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HSLFSheet getSheet(){
|
public HSLFSheet getSheet() {
|
||||||
return this._sheet;
|
return this._sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Shape ID
|
* @return Shape ID
|
||||||
*/
|
*/
|
||||||
protected int getShapeId(){
|
protected int getShapeId() {
|
||||||
return shapeId;
|
return shapeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id Shape ID
|
* @param id Shape ID
|
||||||
*/
|
*/
|
||||||
protected void setShapeId(int id){
|
protected void setShapeId(int id) {
|
||||||
shapeId = id;
|
shapeId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 0-based index of the text run in the SLWT container
|
* @return 0-based index of the text run in the SLWT container
|
||||||
*/
|
*/
|
||||||
protected int getIndex(){
|
protected int getIndex() {
|
||||||
return (_headerAtom != null) ? _headerAtom.getIndex() : -1;
|
return (_headerAtom != null) ? _headerAtom.getIndex() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +177,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
if (_headerAtom != null) _headerAtom.setTextType(runType);
|
if (_headerAtom != null) _headerAtom.setTextType(runType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this Text Run one from a {@link PPDrawing}, or is it
|
* Is this Text Run one from a {@link PPDrawing}, or is it
|
||||||
* one from the {@link SlideListWithText}?
|
* one from the {@link SlideListWithText}?
|
||||||
@ -187,12 +185,12 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
return (getIndex() == -1);
|
return (getIndex() == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextRulerAtom getTextRuler(){
|
public TextRulerAtom getTextRuler() {
|
||||||
return _ruler;
|
return _ruler;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextRulerAtom createTextRuler(){
|
public TextRulerAtom createTextRuler() {
|
||||||
_ruler = getTextRuler();
|
_ruler = getTextRuler();
|
||||||
if (_ruler == null) {
|
if (_ruler == null) {
|
||||||
_ruler = TextRulerAtom.getParagraphInstance();
|
_ruler = TextRulerAtom.getParagraphInstance();
|
||||||
@ -210,9 +208,9 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
*
|
*
|
||||||
* @return text run records
|
* @return text run records
|
||||||
*/
|
*/
|
||||||
public Record[] getRecords(){
|
public Record[] getRecords() {
|
||||||
Record r[] = _headerAtom.getParentRecord().getChildRecords();
|
Record r[] = _headerAtom.getParentRecord().getChildRecords();
|
||||||
return getRecords(r, new int[]{0}, _headerAtom);
|
return getRecords(r, new int[] { 0 }, _headerAtom);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Record[] getRecords(Record[] records, int[] startIdx, TextHeaderAtom headerAtom) {
|
private static Record[] getRecords(Record[] records, int[] startIdx, TextHeaderAtom headerAtom) {
|
||||||
@ -231,7 +229,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
for (length = 1; startIdx[0]+length < records.length; length++) {
|
for (length = 1; startIdx[0] + length < records.length; length++) {
|
||||||
if (records[startIdx[0]+length] instanceof TextHeaderAtom) break;
|
if (records[startIdx[0]+length] instanceof TextHeaderAtom) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,87 +250,63 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
return this.styleTextProp9Atom;
|
return this.styleTextProp9Atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the value of the given Paragraph 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 getParaTextPropVal(String propName) {
|
|
||||||
TextProp prop = _paragraphStyle.findByName(propName);
|
|
||||||
BitMaskTextProp maskProp = (BitMaskTextProp)_paragraphStyle.findByName(ParagraphFlagsTextProp.NAME);
|
|
||||||
boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);
|
|
||||||
if (prop == null && !hardAttribute){
|
|
||||||
HSLFSheet sheet = getSheet();
|
|
||||||
int txtype = getRunType();
|
|
||||||
HSLFMasterSheet master = sheet.getMasterSheet();
|
|
||||||
if (master != null)
|
|
||||||
prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return prop == null ? -1 : prop.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the given Character TextProp, add if required
|
|
||||||
* @param propName The name of the Character TextProp
|
|
||||||
* @param val The value to set for the TextProp
|
|
||||||
*/
|
|
||||||
public void setParaTextPropVal(String propName, int val) {
|
|
||||||
// Ensure we have the StyleTextProp atom we're going to need
|
|
||||||
assert(_paragraphStyle!=null);
|
|
||||||
TextProp tp = fetchOrAddTextProp(_paragraphStyle, propName);
|
|
||||||
tp.setValue(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<HSLFTextRun> iterator() {
|
public Iterator<HSLFTextRun> iterator() {
|
||||||
return _runs.iterator();
|
return _runs.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getLeftMargin() {
|
public Double getLeftMargin() {
|
||||||
int val = getParaTextPropVal("text.offset");
|
TextProp val = getPropVal(_paragraphStyle, "text.offset", this);
|
||||||
return val*HSLFShape.POINT_DPI/((double)HSLFShape.MASTER_DPI);
|
return (val == null) ? null : Units.masterToPoints(val.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLeftMargin(double leftMargin) {
|
public void setLeftMargin(Double leftMargin) {
|
||||||
int val = (int)(leftMargin*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);
|
Integer val = (leftMargin == null) ? null : Units.pointsToMaster(leftMargin);
|
||||||
setParaTextPropVal("text.offset", val);
|
setPropVal(_paragraphStyle, "text.offset", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getRightMargin() {
|
public Double getRightMargin() {
|
||||||
// TODO: find out, how to determine this value
|
// TODO: find out, how to determine this value
|
||||||
return 0;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRightMargin(double rightMargin) {
|
public void setRightMargin(Double rightMargin) {
|
||||||
// TODO: find out, how to set this value
|
// TODO: find out, how to set this value
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getIndent() {
|
public Double getIndent() {
|
||||||
int val = getParaTextPropVal("bullet.offset");
|
TextProp val = getPropVal(_paragraphStyle, "bullet.offset", this);
|
||||||
return val*HSLFShape.POINT_DPI/((double)HSLFShape.MASTER_DPI);
|
return (val == null) ? null : Units.masterToPoints(val.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIndent(double intent) {
|
public void setIndent(Double indent) {
|
||||||
int val = (int)(intent*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);
|
Integer val = (indent == null) ? null : Units.pointsToMaster(indent);
|
||||||
setParaTextPropVal("bullet.offset", val);
|
setPropVal(_paragraphStyle, "bullet.offset", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDefaultFontFamily() {
|
public String getDefaultFontFamily() {
|
||||||
return (_runs.isEmpty() ? "Arial" : _runs.get(0).getFontFamily());
|
String typeface = null;
|
||||||
|
if (!_runs.isEmpty()) {
|
||||||
|
typeface = _runs.get(0).getFontFamily();
|
||||||
|
}
|
||||||
|
return (typeface != null) ? typeface : "Arial";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getDefaultFontSize() {
|
public Double getDefaultFontSize() {
|
||||||
return (_runs.isEmpty() ? 12 : _runs.get(0).getFontSize());
|
Double d = null;
|
||||||
|
if (!_runs.isEmpty()) {
|
||||||
|
d = _runs.get(0).getFontSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (d != null) ? d : 12d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -341,10 +315,10 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
* @param align - the type of alignment
|
* @param align - the type of alignment
|
||||||
*/
|
*/
|
||||||
public void setAlignment(org.apache.poi.sl.usermodel.TextParagraph.TextAlign align) {
|
public void setAlignment(org.apache.poi.sl.usermodel.TextParagraph.TextAlign align) {
|
||||||
int alignInt;
|
Integer alignInt = null;
|
||||||
switch (align) {
|
if (align != null) switch (align) {
|
||||||
default:
|
default:
|
||||||
case LEFT: alignInt = TextAlignmentProp.LEFT; break;
|
case LEFT: alignInt = TextAlignmentProp.LEFT;break;
|
||||||
case CENTER: alignInt = TextAlignmentProp.CENTER; break;
|
case CENTER: alignInt = TextAlignmentProp.CENTER; break;
|
||||||
case RIGHT: alignInt = TextAlignmentProp.RIGHT; break;
|
case RIGHT: alignInt = TextAlignmentProp.RIGHT; break;
|
||||||
case DIST: alignInt = TextAlignmentProp.DISTRIBUTED; break;
|
case DIST: alignInt = TextAlignmentProp.DISTRIBUTED; break;
|
||||||
@ -352,12 +326,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
case JUSTIFY_LOW: alignInt = TextAlignmentProp.JUSTIFYLOW; break;
|
case JUSTIFY_LOW: alignInt = TextAlignmentProp.JUSTIFYLOW; break;
|
||||||
case THAI_DIST: alignInt = TextAlignmentProp.THAIDISTRIBUTED; break;
|
case THAI_DIST: alignInt = TextAlignmentProp.THAIDISTRIBUTED; break;
|
||||||
}
|
}
|
||||||
setParaTextPropVal("alignment", alignInt);
|
setPropVal(_paragraphStyle, "alignment", alignInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.apache.poi.sl.usermodel.TextParagraph.TextAlign getTextAlign() {
|
public org.apache.poi.sl.usermodel.TextParagraph.TextAlign getTextAlign() {
|
||||||
switch (getParaTextPropVal("alignment")) {
|
TextProp tp = getPropVal(_paragraphStyle, "alignment", this);
|
||||||
|
if (tp == null) return null;
|
||||||
|
switch (tp.getValue()) {
|
||||||
default:
|
default:
|
||||||
case TextAlignmentProp.LEFT: return TextAlign.LEFT;
|
case TextAlignmentProp.LEFT: return TextAlign.LEFT;
|
||||||
case TextAlignmentProp.CENTER: return TextAlign.CENTER;
|
case TextAlignmentProp.CENTER: return TextAlign.CENTER;
|
||||||
@ -371,34 +347,33 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FontAlign getFontAlign() {
|
public FontAlign getFontAlign() {
|
||||||
switch(getParaTextPropVal("fontAlign")) {
|
TextProp tp = getPropVal(_paragraphStyle, FontAlignmentProp.NAME, this);
|
||||||
default:
|
if (tp == null) return null;
|
||||||
case -1: return FontAlign.AUTO;
|
|
||||||
|
switch (tp.getValue()) {
|
||||||
case FontAlignmentProp.BASELINE: return FontAlign.BASELINE;
|
case FontAlignmentProp.BASELINE: return FontAlign.BASELINE;
|
||||||
case FontAlignmentProp.TOP: return FontAlign.TOP;
|
case FontAlignmentProp.TOP: return FontAlign.TOP;
|
||||||
case FontAlignmentProp.CENTER: return FontAlign.CENTER;
|
case FontAlignmentProp.CENTER: return FontAlign.CENTER;
|
||||||
case FontAlignmentProp.BOTTOM: return FontAlign.BOTTOM;
|
case FontAlignmentProp.BOTTOM: return FontAlign.BOTTOM;
|
||||||
|
default: return FontAlign.AUTO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BulletStyle getBulletStyle() {
|
public BulletStyle getBulletStyle() {
|
||||||
if (getBulletChar() == 0) return null;
|
if (!isBullet()) return null;
|
||||||
|
|
||||||
return new BulletStyle() {
|
return new BulletStyle() {
|
||||||
public String getBulletCharacter() {
|
public String getBulletCharacter() {
|
||||||
char chr = HSLFTextParagraph.this.getBulletChar();
|
Character chr = HSLFTextParagraph.this.getBulletChar();
|
||||||
return (chr == 0 ? "" : ""+chr);
|
return (chr == null || chr == 0) ? "" : "" + chr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBulletFont() {
|
public String getBulletFont() {
|
||||||
int fontIdx = HSLFTextParagraph.this.getBulletFont();
|
return HSLFTextParagraph.this.getBulletFont();
|
||||||
if (fontIdx == -1) return getDefaultFontFamily();
|
|
||||||
PPFont ppFont = getSheet().getSlideShow().getFont(fontIdx);
|
|
||||||
return ppFont.getFontName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getBulletFontSize() {
|
public Double getBulletFontSize() {
|
||||||
return HSLFTextParagraph.this.getBulletSize();
|
return HSLFTextParagraph.this.getBulletSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +392,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
_parentShape = parentShape;
|
_parentShape = parentShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return indentation level
|
* @return indentation level
|
||||||
@ -449,66 +423,62 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
return getFlag(ParagraphFlagsTextProp.BULLET_IDX);
|
return getFlag(ParagraphFlagsTextProp.BULLET_IDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this rich text run has bullets
|
|
||||||
*/
|
|
||||||
public boolean isBulletHard() {
|
|
||||||
return getFlag(ParagraphFlagsTextProp.BULLET_IDX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the bullet character
|
* Sets the bullet character
|
||||||
*/
|
*/
|
||||||
public void setBulletChar(char c) {
|
public void setBulletChar(Character c) {
|
||||||
setParaTextPropVal("bullet.char", c);
|
Integer val = (c == null) ? null : (int)c.charValue();
|
||||||
|
setPropVal(_paragraphStyle, "bullet.char", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bullet character
|
* Returns the bullet character
|
||||||
*/
|
*/
|
||||||
public char getBulletChar() {
|
public Character getBulletChar() {
|
||||||
int val = getParaTextPropVal("bullet.char");
|
TextProp tp = getPropVal(_paragraphStyle, "bullet.char", this);
|
||||||
return (char)(val == -1 ? 0 : val);
|
return (tp == null) ? null : (char)tp.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the bullet size
|
* Sets the bullet size
|
||||||
*/
|
*/
|
||||||
public void setBulletSize(int size) {
|
public void setBulletSize(Double size) {
|
||||||
setParaTextPropVal("bullet.size", size);
|
setPctOrPoints("bullet.size", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bullet size
|
* Returns the bullet size, null if unset
|
||||||
*/
|
*/
|
||||||
public int getBulletSize() {
|
public Double getBulletSize() {
|
||||||
return getParaTextPropVal("bullet.size");
|
return getPctOrPoints("bullet.size");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the bullet color
|
* Sets the bullet color
|
||||||
*/
|
*/
|
||||||
public void setBulletColor(Color color) {
|
public void setBulletColor(Color color) {
|
||||||
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB();
|
Integer val = (color == null) ? null : new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB();
|
||||||
setParaTextPropVal("bullet.color", rgb);
|
setPropVal(_paragraphStyle, "bullet.color", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bullet color
|
* Returns the bullet color
|
||||||
*/
|
*/
|
||||||
public Color getBulletColor() {
|
public Color getBulletColor() {
|
||||||
int rgb = getParaTextPropVal("bullet.color");
|
TextProp tp = getPropVal(_paragraphStyle, "bullet.color", this);
|
||||||
if (rgb == -1) {
|
if (tp == null) {
|
||||||
// if bullet color is undefined, return color of first run
|
// if bullet color is undefined, return color of first run
|
||||||
if (_runs.isEmpty()) return null;
|
return (_runs.isEmpty()) ? null : _runs.get(0).getFontColor();
|
||||||
return _runs.get(0).getFontColor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rgb = tp.getValue();
|
||||||
int cidx = rgb >> 24;
|
int cidx = rgb >> 24;
|
||||||
if (rgb % 0x1000000 == 0){
|
if (rgb % 0x1000000 == 0) {
|
||||||
if (_sheet == null) return null;
|
if (_sheet == null)
|
||||||
|
return null;
|
||||||
ColorSchemeAtom ca = _sheet.getColorScheme();
|
ColorSchemeAtom ca = _sheet.getColorScheme();
|
||||||
if(cidx >= 0 && cidx <= 7) rgb = ca.getColor(cidx);
|
if (cidx >= 0 && cidx <= 7)
|
||||||
|
rgb = ca.getColor(cidx);
|
||||||
}
|
}
|
||||||
Color tmp = new Color(rgb, true);
|
Color tmp = new Color(rgb, true);
|
||||||
return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
|
return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
|
||||||
@ -517,124 +487,133 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
/**
|
/**
|
||||||
* Sets the bullet font
|
* Sets the bullet font
|
||||||
*/
|
*/
|
||||||
public void setBulletFont(int idx) {
|
public void setBulletFont(String typeface) {
|
||||||
setParaTextPropVal("bullet.font", idx);
|
if (typeface == null) {
|
||||||
|
setPropVal(_paragraphStyle, "bullet.font", null);
|
||||||
|
setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FontCollection fc = getSheet().getSlideShow().getFontCollection();
|
||||||
|
int idx = fc.addFont(typeface);
|
||||||
|
|
||||||
|
setPropVal(_paragraphStyle, "bullet.font", idx);
|
||||||
setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, true);
|
setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bullet font
|
* Returns the bullet font
|
||||||
*/
|
*/
|
||||||
public int getBulletFont() {
|
public String getBulletFont() {
|
||||||
return getParaTextPropVal("bullet.font");
|
TextProp tp = getPropVal(_paragraphStyle, "bullet.font", this);
|
||||||
|
if (tp == null) return getDefaultFontFamily();
|
||||||
|
PPFont ppFont = getSheet().getSlideShow().getFont(tp.getValue());
|
||||||
|
assert(ppFont != null);
|
||||||
|
return ppFont.getFontName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLineSpacing(double lineSpacing) {
|
public void setLineSpacing(Double lineSpacing) {
|
||||||
// if lineSpacing < 0, we need to convert points (common interface) to master units (hslf)
|
setPctOrPoints("linespacing", lineSpacing);
|
||||||
if (lineSpacing < 0) {
|
|
||||||
lineSpacing = (lineSpacing*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);
|
|
||||||
}
|
|
||||||
setParaTextPropVal("linespacing", (int)lineSpacing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getLineSpacing() {
|
public Double getLineSpacing() {
|
||||||
double val = getParaTextPropVal("linespacing");
|
return getPctOrPoints("linespacing");
|
||||||
// if lineSpacing < 0, we need to convert master units (hslf) to points (common interface)
|
|
||||||
if (val == -1) return 0;
|
|
||||||
if (val < -1) val *= HSLFShape.POINT_DPI/((double)HSLFShape.MASTER_DPI);
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets spacing before a paragraph.
|
|
||||||
* <p>
|
|
||||||
* If spacebefore >= 0, then spacebefore is a percentage of normal line height.
|
|
||||||
* If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public void setSpaceBefore(int val) {
|
|
||||||
setParaTextPropVal("spacebefore", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns spacing before a paragraph
|
|
||||||
* <p>
|
|
||||||
* If spacebefore >= 0, then spacebefore is a percentage of normal line height.
|
|
||||||
* If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return the spacing before a paragraph
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public double getSpaceBefore() {
|
public void setSpaceBefore(Double spaceBefore) {
|
||||||
int val = getParaTextPropVal("spacebefore");
|
setPctOrPoints("spacebefore", spaceBefore);
|
||||||
return val == -1 ? 0 : val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets spacing after a paragraph.
|
|
||||||
* <p>
|
|
||||||
* If spaceafter >= 0, then spaceafter is a percentage of normal line height.
|
|
||||||
* If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public void setSpaceAfter(int val) {
|
|
||||||
setParaTextPropVal("spaceafter", val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns spacing after a paragraph
|
|
||||||
* <p>
|
|
||||||
* If spaceafter >= 0, then spaceafter is a percentage of normal line height.
|
|
||||||
* If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return the spacing before a paragraph
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public double getSpaceAfter() {
|
public Double getSpaceBefore() {
|
||||||
int val = getParaTextPropVal("spaceafter");
|
return getPctOrPoints("spacebefore");
|
||||||
return val == -1 ? 0 : val;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpaceAfter(Double spaceAfter) {
|
||||||
|
setPctOrPoints("spaceafter", spaceAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getSpaceAfter() {
|
||||||
|
return getPctOrPoints("spaceafter");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getDefaultTabSize() {
|
||||||
|
// TODO: implement
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double getPctOrPoints(String propName) {
|
||||||
|
TextProp tp = getPropVal(_paragraphStyle, propName, this);
|
||||||
|
if (tp == null) return null;
|
||||||
|
int val = tp.getValue();
|
||||||
|
return (val < 0) ? Units.masterToPoints(val) : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPctOrPoints(String propName, Double dval) {
|
||||||
|
Integer ival = null;
|
||||||
|
if (dval != null) {
|
||||||
|
ival = (dval < 0) ? Units.pointsToMaster(dval) : dval.intValue();
|
||||||
|
}
|
||||||
|
setPropVal(_paragraphStyle, propName, ival);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getFlag(int index) {
|
||||||
|
BitMaskTextProp tp = (BitMaskTextProp)getPropVal(_paragraphStyle, ParagraphFlagsTextProp.NAME, this);
|
||||||
|
return (tp == null) ? false : tp.getSubValue(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFlag(int index, boolean value) {
|
||||||
|
BitMaskTextProp tp = (BitMaskTextProp)_paragraphStyle.addWithName(ParagraphFlagsTextProp.NAME);
|
||||||
|
tp.setSubValue(value, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the named TextProp, either by fetching it (if it exists) or adding it
|
* Fetch the value of the given Paragraph related TextProp. Returns null if
|
||||||
* (if it didn't)
|
* that TextProp isn't present. If the TextProp isn't present, the value
|
||||||
* @param textPropCol The TextPropCollection to fetch from / add into
|
* from the appropriate Master Sheet will apply.
|
||||||
* @param textPropName The name of the TextProp to fetch/add
|
|
||||||
*/
|
*/
|
||||||
protected static TextProp fetchOrAddTextProp(TextPropCollection textPropCol, String textPropName) {
|
protected static TextProp getPropVal(TextPropCollection props, String propName, HSLFTextParagraph paragraph) {
|
||||||
// Fetch / Add the TextProp
|
TextProp prop = props.findByName(propName);
|
||||||
return textPropCol.addWithName(textPropName);
|
if (prop != null) return prop;
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean getFlag(int index) {
|
BitMaskTextProp maskProp = (BitMaskTextProp) props.findByName(ParagraphFlagsTextProp.NAME);
|
||||||
if (_paragraphStyle == null) return false;
|
boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);
|
||||||
|
if (hardAttribute) return null;
|
||||||
|
|
||||||
BitMaskTextProp prop = (BitMaskTextProp) _paragraphStyle.findByName(ParagraphFlagsTextProp.NAME);
|
HSLFSheet sheet = paragraph.getSheet();
|
||||||
|
int txtype = paragraph.getRunType();
|
||||||
if (prop == null) {
|
HSLFMasterSheet master = sheet.getMasterSheet();
|
||||||
if (_sheet != null) {
|
if (master == null) {
|
||||||
int txtype = getRunType();
|
|
||||||
HSLFMasterSheet master = _sheet.getMasterSheet();
|
|
||||||
if (master != null) {
|
|
||||||
prop = (BitMaskTextProp) master.getStyleAttribute(txtype, getIndentLevel(), ParagraphFlagsTextProp.NAME, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.log(POILogger.WARN, "MasterSheet is not available");
|
logger.log(POILogger.WARN, "MasterSheet is not available");
|
||||||
}
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return prop == null ? false : prop.getSubValue(index);
|
boolean isChar = props.getTextPropType() == TextPropType.character;
|
||||||
|
return master.getStyleAttribute(txtype, paragraph.getIndentLevel(), propName, isChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setFlag(int index, boolean value) {
|
/**
|
||||||
// Ensure we have the StyleTextProp atom we're going to need
|
* Returns the named TextProp, either by fetching it (if it exists) or
|
||||||
assert(_paragraphStyle!=null);
|
* adding it (if it didn't)
|
||||||
BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME);
|
*
|
||||||
prop.setSubValue(value,index);
|
* @param props the TextPropCollection to fetch from / add into
|
||||||
|
* @param name the name of the TextProp to fetch/add
|
||||||
|
* @param val the value, null if unset
|
||||||
|
*/
|
||||||
|
protected static void setPropVal(TextPropCollection props, String name, Integer val) {
|
||||||
|
if (val == null) {
|
||||||
|
props.removeByName(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch / Add the TextProp
|
||||||
|
TextProp tp = props.addWithName(name);
|
||||||
|
tp.setValue(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -646,14 +625,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
HSLFTextRun lastRun = null;
|
HSLFTextRun lastRun = null;
|
||||||
for (HSLFTextParagraph p : paragraphs) {
|
for (HSLFTextParagraph p : paragraphs) {
|
||||||
if (lastRun != null && !lastRun.getRawText().endsWith("\r")) {
|
if (lastRun != null && !lastRun.getRawText().endsWith("\r")) {
|
||||||
lastRun.setText(lastRun.getRawText()+"\r");
|
lastRun.setText(lastRun.getRawText() + "\r");
|
||||||
}
|
}
|
||||||
List<HSLFTextRun> ltr = p.getTextRuns();
|
List<HSLFTextRun> ltr = p.getTextRuns();
|
||||||
if (ltr.isEmpty()) {
|
if (ltr.isEmpty()) {
|
||||||
throw new RuntimeException("paragraph without textruns found");
|
throw new RuntimeException("paragraph without textruns found");
|
||||||
}
|
}
|
||||||
lastRun = ltr.get(ltr.size()-1);
|
lastRun = ltr.get(ltr.size() - 1);
|
||||||
assert(lastRun.getRawText() != null);
|
assert (lastRun.getRawText() != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +654,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
afterHeader |= (header == record);
|
afterHeader |= (header == record);
|
||||||
if (afterHeader && rt == RecordTypes.StyleTextPropAtom.typeID) {
|
if (afterHeader && rt == RecordTypes.StyleTextPropAtom.typeID) {
|
||||||
// found it
|
// found it
|
||||||
style = (StyleTextPropAtom)record;
|
style = (StyleTextPropAtom) record;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,7 +670,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the modified paragraphs/textrun to the records.
|
* Saves the modified paragraphs/textrun to the records.
|
||||||
* Also updates the styles to the correct text length.
|
* Also updates the styles to the correct text length.
|
||||||
@ -726,15 +704,15 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
}
|
}
|
||||||
newRecord = byteAtom;
|
newRecord = byteAtom;
|
||||||
byte[] byteText = new byte[rawText.length()];
|
byte[] byteText = new byte[rawText.length()];
|
||||||
StringUtil.putCompressedUnicode(rawText,byteText,0);
|
StringUtil.putCompressedUnicode(rawText, byteText, 0);
|
||||||
byteAtom.setText(byteText);
|
byteAtom.setText(byteText);
|
||||||
}
|
}
|
||||||
assert(newRecord != null);
|
assert (newRecord != null);
|
||||||
|
|
||||||
RecordContainer _txtbox = headerAtom.getParentRecord();
|
RecordContainer _txtbox = headerAtom.getParentRecord();
|
||||||
Record[] cr = _txtbox.getChildRecords();
|
Record[] cr = _txtbox.getChildRecords();
|
||||||
int headerIdx = -1, textIdx = -1, styleIdx = -1;
|
int headerIdx = -1, textIdx = -1, styleIdx = -1;
|
||||||
for (int i=0; i<cr.length; i++) {
|
for (int i = 0; i < cr.length; i++) {
|
||||||
Record r = cr[i];
|
Record r = cr[i];
|
||||||
if (r == headerAtom) headerIdx = i;
|
if (r == headerAtom) headerIdx = i;
|
||||||
else if (r == oldRecord || r == newRecord) textIdx = i;
|
else if (r == oldRecord || r == newRecord) textIdx = i;
|
||||||
@ -744,7 +722,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
if (textIdx == -1) {
|
if (textIdx == -1) {
|
||||||
// the old record was never registered, ignore it
|
// the old record was never registered, ignore it
|
||||||
_txtbox.addChildAfter(newRecord, headerAtom);
|
_txtbox.addChildAfter(newRecord, headerAtom);
|
||||||
textIdx = headerIdx+1;
|
textIdx = headerIdx + 1;
|
||||||
} else {
|
} else {
|
||||||
// swap not appropriated records - noop if unchanged
|
// swap not appropriated records - noop if unchanged
|
||||||
cr[textIdx] = newRecord;
|
cr[textIdx] = newRecord;
|
||||||
@ -787,18 +765,18 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
lastRTPC.copy(rtpc);
|
lastRTPC.copy(rtpc);
|
||||||
}
|
}
|
||||||
int len = tr.getLength();
|
int len = tr.getLength();
|
||||||
ptpc.updateTextSize(ptpc.getCharactersCovered()+len);
|
ptpc.updateTextSize(ptpc.getCharactersCovered() + len);
|
||||||
rtpc.updateTextSize(len);
|
rtpc.updateTextSize(len);
|
||||||
lastPTPC.updateTextSize(lastPTPC.getCharactersCovered()+len);
|
lastPTPC.updateTextSize(lastPTPC.getCharactersCovered() + len);
|
||||||
lastRTPC.updateTextSize(lastRTPC.getCharactersCovered()+len);
|
lastRTPC.updateTextSize(lastRTPC.getCharactersCovered() + len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(lastPTPC != null && lastRTPC != null && ptpc != null && rtpc != null);
|
assert (lastPTPC != null && lastRTPC != null && ptpc != null && rtpc != null);
|
||||||
ptpc.updateTextSize(ptpc.getCharactersCovered()+1);
|
ptpc.updateTextSize(ptpc.getCharactersCovered() + 1);
|
||||||
rtpc.updateTextSize(rtpc.getCharactersCovered()+1);
|
rtpc.updateTextSize(rtpc.getCharactersCovered() + 1);
|
||||||
lastPTPC.updateTextSize(lastPTPC.getCharactersCovered()+1);
|
lastPTPC.updateTextSize(lastPTPC.getCharactersCovered() + 1);
|
||||||
lastRTPC.updateTextSize(lastRTPC.getCharactersCovered()+1);
|
lastRTPC.updateTextSize(lastRTPC.getCharactersCovered() + 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If TextSpecInfoAtom is present, we must update the text size in it,
|
* If TextSpecInfoAtom is present, we must update the text size in it,
|
||||||
@ -806,14 +784,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
*/
|
*/
|
||||||
for (Record r : paragraphs.get(0).getRecords()) {
|
for (Record r : paragraphs.get(0).getRecords()) {
|
||||||
if (r instanceof TextSpecInfoAtom) {
|
if (r instanceof TextSpecInfoAtom) {
|
||||||
((TextSpecInfoAtom)r).setParentSize(rawText.length()+1);
|
((TextSpecInfoAtom) r).setParentSize(rawText.length() + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_txtbox instanceof EscherTextboxWrapper) {
|
if (_txtbox instanceof EscherTextboxWrapper) {
|
||||||
try {
|
try {
|
||||||
((EscherTextboxWrapper)_txtbox).writeOut(null);
|
((EscherTextboxWrapper) _txtbox).writeOut(null);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("failed dummy write", e);
|
throw new RuntimeException("failed dummy write", e);
|
||||||
}
|
}
|
||||||
@ -832,8 +810,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
// check paragraphs
|
// check paragraphs
|
||||||
assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());
|
assert(!paragraphs.isEmpty() && !paragraphs.get(0).getTextRuns().isEmpty());
|
||||||
|
|
||||||
HSLFTextParagraph htp = paragraphs.get(paragraphs.size()-1);
|
HSLFTextParagraph htp = paragraphs.get(paragraphs.size() - 1);
|
||||||
HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size()-1);
|
HSLFTextRun htr = htp.getTextRuns().get(htp.getTextRuns().size() - 1);
|
||||||
|
|
||||||
boolean isFirst = !newParagraph;
|
boolean isFirst = !newParagraph;
|
||||||
for (String rawText : text.split("(?<=\r)")) {
|
for (String rawText : text.split("(?<=\r)")) {
|
||||||
@ -876,7 +854,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
|
|
||||||
Iterator<HSLFTextParagraph> paraIter = paragraphs.iterator();
|
Iterator<HSLFTextParagraph> paraIter = paragraphs.iterator();
|
||||||
HSLFTextParagraph htp = paraIter.next(); // keep first
|
HSLFTextParagraph htp = paraIter.next(); // keep first
|
||||||
assert(htp != null);
|
assert (htp != null);
|
||||||
while (paraIter.hasNext()) {
|
while (paraIter.hasNext()) {
|
||||||
paraIter.next();
|
paraIter.next();
|
||||||
paraIter.remove();
|
paraIter.remove();
|
||||||
@ -885,7 +863,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
Iterator<HSLFTextRun> runIter = htp.getTextRuns().iterator();
|
Iterator<HSLFTextRun> runIter = htp.getTextRuns().iterator();
|
||||||
HSLFTextRun htr = runIter.next();
|
HSLFTextRun htr = runIter.next();
|
||||||
htr.setText("");
|
htr.setText("");
|
||||||
assert(htr != null);
|
assert (htr != null);
|
||||||
while (runIter.hasNext()) {
|
while (runIter.hasNext()) {
|
||||||
runIter.next();
|
runIter.next();
|
||||||
runIter.remove();
|
runIter.remove();
|
||||||
@ -895,7 +873,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getText(List<HSLFTextParagraph> paragraphs) {
|
public static String getText(List<HSLFTextParagraph> paragraphs) {
|
||||||
assert(!paragraphs.isEmpty());
|
assert (!paragraphs.isEmpty());
|
||||||
String rawText = getRawText(paragraphs);
|
String rawText = getRawText(paragraphs);
|
||||||
return toExternalString(rawText, paragraphs.get(0).getRunType());
|
return toExternalString(rawText, paragraphs.get(0).getRunType());
|
||||||
}
|
}
|
||||||
@ -982,7 +960,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs();
|
List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs();
|
||||||
assert(sheetRuns != null);
|
assert (sheetRuns != null);
|
||||||
|
|
||||||
int idx = ota.getTextIndex();
|
int idx = ota.getTextIndex();
|
||||||
for (List<HSLFTextParagraph> r : sheetRuns) {
|
for (List<HSLFTextParagraph> r : sheetRuns) {
|
||||||
@ -1000,14 +978,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rv == null || rv.isEmpty()) {
|
if (rv == null || rv.isEmpty()) {
|
||||||
logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
|
logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sheet != null) {
|
if (sheet != null) {
|
||||||
// check sheet runs first, so we get exactly the same paragraph list
|
// check sheet runs first, so we get exactly the same paragraph list
|
||||||
List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs();
|
List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs();
|
||||||
assert(sheetRuns != null);
|
assert (sheetRuns != null);
|
||||||
|
|
||||||
for (List<HSLFTextParagraph> paras : sheetRuns) {
|
for (List<HSLFTextParagraph> paras : sheetRuns) {
|
||||||
if (!paras.isEmpty() && paras.get(0)._headerAtom.getParentRecord() == wrapper) {
|
if (!paras.isEmpty() && paras.get(0)._headerAtom.getParentRecord() == wrapper) {
|
||||||
@ -1050,7 +1028,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records) {
|
protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records) {
|
||||||
List<List<HSLFTextParagraph>> paragraphCollection = new ArrayList<List<HSLFTextParagraph>>();
|
List<List<HSLFTextParagraph>> paragraphCollection = new ArrayList<List<HSLFTextParagraph>>();
|
||||||
|
|
||||||
int[] recordIdx = {0};
|
int[] recordIdx = { 0 };
|
||||||
|
|
||||||
for (int slwtIndex = 0; recordIdx[0] < records.length; slwtIndex++) {
|
for (int slwtIndex = 0; recordIdx[0] < records.length; slwtIndex++) {
|
||||||
TextHeaderAtom header = null;
|
TextHeaderAtom header = null;
|
||||||
@ -1062,15 +1040,15 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
for (Record r : getRecords(records, recordIdx, null)) {
|
for (Record r : getRecords(records, recordIdx, null)) {
|
||||||
long rt = r.getRecordType();
|
long rt = r.getRecordType();
|
||||||
if (RecordTypes.TextHeaderAtom.typeID == rt) {
|
if (RecordTypes.TextHeaderAtom.typeID == rt) {
|
||||||
header = (TextHeaderAtom)r;
|
header = (TextHeaderAtom) r;
|
||||||
} else if (RecordTypes.TextBytesAtom.typeID == rt) {
|
} else if (RecordTypes.TextBytesAtom.typeID == rt) {
|
||||||
tbytes = (TextBytesAtom)r;
|
tbytes = (TextBytesAtom) r;
|
||||||
} else if (RecordTypes.TextCharsAtom.typeID == rt) {
|
} else if (RecordTypes.TextCharsAtom.typeID == rt) {
|
||||||
tchars = (TextCharsAtom)r;
|
tchars = (TextCharsAtom) r;
|
||||||
} else if (RecordTypes.TextRulerAtom.typeID == rt) {
|
} else if (RecordTypes.TextRulerAtom.typeID == rt) {
|
||||||
ruler = (TextRulerAtom)r;
|
ruler = (TextRulerAtom) r;
|
||||||
} else if (RecordTypes.MasterTextPropAtom.typeID == rt) {
|
} else if (RecordTypes.MasterTextPropAtom.typeID == rt) {
|
||||||
indents = (MasterTextPropAtom)r;
|
indents = (MasterTextPropAtom) r;
|
||||||
}
|
}
|
||||||
// don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below
|
// don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below
|
||||||
}
|
}
|
||||||
@ -1124,25 +1102,25 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
int paraIdx = 0, runIdx = 0;
|
int paraIdx = 0, runIdx = 0;
|
||||||
HSLFTextRun trun;
|
HSLFTextRun trun;
|
||||||
|
|
||||||
for (int csIdx=0; csIdx<charStyles.size(); csIdx++) {
|
for (int csIdx = 0; csIdx < charStyles.size(); csIdx++) {
|
||||||
TextPropCollection p = charStyles.get(csIdx);
|
TextPropCollection p = charStyles.get(csIdx);
|
||||||
for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle; ) {
|
for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle;) {
|
||||||
HSLFTextParagraph para = paragraphs.get(paraIdx);
|
HSLFTextParagraph para = paragraphs.get(paraIdx);
|
||||||
List<HSLFTextRun> runs = para.getTextRuns();
|
List<HSLFTextRun> runs = para.getTextRuns();
|
||||||
trun = runs.get(runIdx);
|
trun = runs.get(runIdx);
|
||||||
int len = trun.getLength();
|
int len = trun.getLength();
|
||||||
|
|
||||||
if (ccRun+len <= ccStyle) {
|
if (ccRun + len <= ccStyle) {
|
||||||
ccRun += len;
|
ccRun += len;
|
||||||
} else {
|
} else {
|
||||||
String text = trun.getRawText();
|
String text = trun.getRawText();
|
||||||
trun.setText(text.substring(0,ccStyle-ccRun));
|
trun.setText(text.substring(0, ccStyle - ccRun));
|
||||||
|
|
||||||
HSLFTextRun nextRun = new HSLFTextRun(para);
|
HSLFTextRun nextRun = new HSLFTextRun(para);
|
||||||
nextRun.setText(text.substring(ccStyle-ccRun));
|
nextRun.setText(text.substring(ccStyle - ccRun));
|
||||||
runs.add(runIdx+1, nextRun);
|
runs.add(runIdx + 1, nextRun);
|
||||||
|
|
||||||
ccRun += ccStyle-ccRun;
|
ccRun += ccStyle - ccRun;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextPropCollection pCopy = new TextPropCollection(0, TextPropType.character);
|
TextPropCollection pCopy = new TextPropCollection(0, TextPropType.character);
|
||||||
@ -1151,7 +1129,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
|
|
||||||
len = trun.getLength();
|
len = trun.getLength();
|
||||||
if (paraIdx == paragraphs.size()-1 && runIdx == runs.size()-1) {
|
if (paraIdx == paragraphs.size()-1 && runIdx == runs.size()-1) {
|
||||||
if (csIdx < charStyles.size()-1) {
|
if (csIdx < charStyles.size() - 1) {
|
||||||
// special case, empty trailing text run
|
// special case, empty trailing text run
|
||||||
HSLFTextRun nextRun = new HSLFTextRun(para);
|
HSLFTextRun nextRun = new HSLFTextRun(para);
|
||||||
nextRun.setText("");
|
nextRun.setText("");
|
||||||
@ -1204,7 +1182,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
len += trun.getLength();
|
len += trun.getLength();
|
||||||
}
|
}
|
||||||
para.setIndentLevel(p.getIndentLevel());
|
para.setIndentLevel(p.getIndentLevel());
|
||||||
ccPara += len+1;
|
ccPara += len + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1237,6 +1215,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public EscherTextboxWrapper getTextboxWrapper() {
|
public EscherTextboxWrapper getTextboxWrapper() {
|
||||||
return (EscherTextboxWrapper)_headerAtom.getParentRecord();
|
return (EscherTextboxWrapper) _headerAtom.getParentRecord();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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",
|
||||||
|
"alterman_security2.pptx",
|
||||||
|
};
|
||||||
|
|
||||||
|
BitSet pages = new BitSet();
|
||||||
|
pages.set(2);
|
||||||
|
|
||||||
|
for (String file : files) {
|
||||||
InputStream is = _slTests.openResourceAsStream(file);
|
InputStream is = _slTests.openResourceAsStream(file);
|
||||||
SlideShow ss = file.endsWith("pptx") ? new XMLSlideShow(is) : new HSLFSlideShow(is);
|
SlideShow ss = file.endsWith("pptx") ? new XMLSlideShow(is) : new HSLFSlideShow(is);
|
||||||
is.close();
|
is.close();
|
||||||
|
|
||||||
boolean debugOut = false;
|
boolean debugOut = false;
|
||||||
Dimension pg = ss.getPageSize();
|
Dimension pg = ss.getPageSize();
|
||||||
int i=1;
|
for (Slide<?,?,?> slide : ss.getSlides()) {
|
||||||
for(Slide<?,?,?> slide : ss.getSlides()) {
|
int slideNo = slide.getSlideNumber();
|
||||||
|
if (!pages.get(slideNo-1)) {
|
||||||
|
if (pages.nextSetBit(slideNo-1) == -1) break; else continue;
|
||||||
|
}
|
||||||
if (debugOut) {
|
if (debugOut) {
|
||||||
DummyGraphics2d graphics = new DummyGraphics2d();
|
DummyGraphics2d graphics = new DummyGraphics2d();
|
||||||
slide.draw(graphics);
|
slide.draw(graphics);
|
||||||
} else {
|
} else {
|
||||||
BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB);
|
BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_ARGB);
|
||||||
Graphics2D graphics = img.createGraphics();
|
Graphics2D graphics = img.createGraphics();
|
||||||
fixFonts(graphics);
|
fixFonts(graphics);
|
||||||
slide.draw(graphics);
|
slide.draw(graphics);
|
||||||
ImageIO.write(img, "PNG", new File("test"+(i++)+"hslf.png"));
|
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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
test-data/slideshow/alterman_security2.pptx
Normal file
BIN
test-data/slideshow/alterman_security2.pptx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user