Creating a new slideshow and manipulating existing ones works again :)

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1681389 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2015-05-23 22:07:05 +00:00
parent fd637ce0ed
commit d49b2b6b51
9 changed files with 361 additions and 352 deletions

View File

@ -20,6 +20,7 @@ package org.apache.poi.hslf.examples;
import java.awt.*; import java.awt.*;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import org.apache.poi.hslf.model.*; import org.apache.poi.hslf.model.*;
import org.apache.poi.hslf.record.TextHeaderAtom; import org.apache.poi.hslf.record.TextHeaderAtom;
@ -113,33 +114,29 @@ public final class ApacheconEU08 {
slide.addShape(box1); slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox(); HSLFTextBox box2 = new HSLFTextBox();
box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(28);
box2.setRunType(TextHeaderAtom.BODY_TYPE); box2.setRunType(TextHeaderAtom.BODY_TYPE);
box2.setText( box2.setText(
"HSLF provides a way to read, create and modify MS PowerPoint presentations\r" + "HSLF provides a way to read, create and modify MS PowerPoint presentations\r" +
"Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" + "Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" +
"Comprehensive support of PowerPoint objects"); "Comprehensive support of PowerPoint objects\r" +
box2.setAnchor(new Rectangle(36, 80, 648, 200));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
box2.getTextParagraphs().get(0).setIndentLevel(1);
box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(24);
box3.setRunType(TextHeaderAtom.BODY_TYPE);
box3.setText(
"Rich text\r" + "Rich text\r" +
"Tables\r" + "Tables\r" +
"Shapes\r" + "Shapes\r" +
"Pictures\r" + "Pictures\r" +
"Master slides"); "Master slides\r" +
box3.setAnchor(new Rectangle(36, 265, 648, 150)); "Access to low level data structures"
slide.addShape(box3); );
HSLFTextBox box4 = new HSLFTextBox(); List<HSLFTextParagraph> tp = box2.getTextParagraphs();
box4.setRunType(TextHeaderAtom.BODY_TYPE); for (int i : new byte[]{0,1,2,8}) {
box4.setText("Access to low level data structures"); tp.get(i).getTextRuns().get(0).setFontSize(28);
box4.setAnchor(new Rectangle(36, 430, 648, 50)); }
slide.addShape(box4); for (int i : new byte[]{3,4,5,6,7}) {
tp.get(i).getTextRuns().get(0).setFontSize(24);
tp.get(i).setIndentLevel(1);
}
box2.setAnchor(new Rectangle(36, 80, 648, 400));
slide.addShape(box2);
} }
public static void slide4(HSLFSlideShow ppt) throws IOException { public static void slide4(HSLFSlideShow ppt) throws IOException {
@ -238,40 +235,41 @@ public final class ApacheconEU08 {
rt3.setFontName("Courier New"); rt3.setFontName("Courier New");
rt3.setFontSize(8); rt3.setFontSize(8);
box3.setText( box3.setText(
" SlideShow ppt = new SlideShow();\r" + "SlideShow ppt = new SlideShow();\u000b" +
" Slide slide = ppt.createSlide();\r" + "Slide slide = ppt.createSlide();\u000b" +
"\r" + "\u000b" +
" TextBox box2 = new TextBox();\r" + "TextBox box2 = new TextBox();\u000b" +
" box2.setHorizontalAlignment(TextBox.AlignCenter);\r" + "box2.setHorizontalAlignment(TextBox.AlignCenter);\u000b" +
" box2.setVerticalAlignment(TextBox.AnchorMiddle);\r" + "box2.setVerticalAlignment(TextBox.AnchorMiddle);\u000b" +
" box2.getTextRun().setText(\"Java Code\");\r" + "box2.getTextRun().setText(\"Java Code\");\u000b" +
" box2.getFill().setForegroundColor(new Color(187, 224, 227));\r" + "box2.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
" box2.setLineColor(Color.black);\r" + "box2.setLineColor(Color.black);\u000b" +
" box2.setLineWidth(0.75);\r" + "box2.setLineWidth(0.75);\u000b" +
" box2.setAnchor(new Rectangle(66, 243, 170, 170));\r" + "box2.setAnchor(new Rectangle(66, 243, 170, 170));\u000b" +
" slide.addShape(box2);\r" + "slide.addShape(box2);\u000b" +
"\r" + "\u000b" +
" TextBox box3 = new TextBox();\r" + "TextBox box3 = new TextBox();\u000b" +
" box3.setHorizontalAlignment(TextBox.AlignCenter);\r" + "box3.setHorizontalAlignment(TextBox.AlignCenter);\u000b" +
" box3.setVerticalAlignment(TextBox.AnchorMiddle);\r" + "box3.setVerticalAlignment(TextBox.AnchorMiddle);\u000b" +
" box3.getTextRun().setText(\"*.ppt file\");\r" + "box3.getTextRun().setText(\"*.ppt file\");\u000b" +
" box3.setLineWidth(0.75);\r" + "box3.setLineWidth(0.75);\u000b" +
" box3.setLineColor(Color.black);\r" + "box3.setLineColor(Color.black);\u000b" +
" box3.getFill().setForegroundColor(new Color(187, 224, 227));\r" + "box3.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
" box3.setAnchor(new Rectangle(473, 243, 170, 170));\r" + "box3.setAnchor(new Rectangle(473, 243, 170, 170));\u000b" +
" slide.addShape(box3);\r" + "slide.addShape(box3);\u000b" +
"\r" + "\u000b" +
" AutoShape box4 = new AutoShape(ShapeTypes.Arrow);\r" + "AutoShape box4 = new AutoShape(ShapeTypes.Arrow);\u000b" +
" box4.getFill().setForegroundColor(new Color(187, 224, 227));\r" + "box4.getFill().setForegroundColor(new Color(187, 224, 227));\u000b" +
" box4.setLineWidth(0.75);\r" + "box4.setLineWidth(0.75);\u000b" +
" box4.setLineColor(Color.black);\r" + "box4.setLineColor(Color.black);\u000b" +
" box4.setAnchor(new Rectangle(253, 288, 198, 85));\r" + "box4.setAnchor(new Rectangle(253, 288, 198, 85));\u000b" +
" slide.addShape(box4);\r" + "slide.addShape(box4);\u000b" +
"\r" + "\u000b" +
" FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\r" + "FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\u000b" +
" ppt.write(out);\r" + "ppt.write(out);\u000b" +
" out.close();"); "out.close();");
box3.setAnchor(new Rectangle(30, 150, 618, 411)); box3.setAnchor(new Rectangle(30, 150, 618, 411));
box3.setHorizontalCentered(true);
slide.addShape(box3); slide.addShape(box3);
} }
@ -346,45 +344,46 @@ public final class ApacheconEU08 {
rt3.setFontName("Courier New"); rt3.setFontName("Courier New");
rt3.setFontSize(8); rt3.setFontSize(8);
box3.setText( box3.setText(
" //bar chart data. The first value is the bar color, the second is the width\r" + "//bar chart data. The first value is the bar color, the second is the width\u000b" +
" Object[] def = new Object[]{\r" + "Object[] def = new Object[]{\u000b" +
" Color.yellow, new Integer(100),\r" + " Color.yellow, new Integer(100),\u000b" +
" Color.green, new Integer(150),\r" + " Color.green, new Integer(150),\u000b" +
" Color.gray, new Integer(75),\r" + " Color.gray, new Integer(75),\u000b" +
" Color.red, new Integer(200),\r" + " Color.red, new Integer(200),\u000b" +
" };\r" + "};\u000b" +
"\r" + "\u000b" +
" SlideShow ppt = new SlideShow();\r" + "SlideShow ppt = new SlideShow();\u000b" +
" Slide slide = ppt.createSlide();\r" + "Slide slide = ppt.createSlide();\u000b" +
"\r" + "\u000b" +
" ShapeGroup group = new ShapeGroup();\r" + "ShapeGroup group = new ShapeGroup();\u000b" +
" //define position of the drawing in the slide\r" + "//define position of the drawing in the slide\u000b" +
" Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);\r" + "Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);\u000b" +
" group.setAnchor(bounds);\r" + "group.setAnchor(bounds);\u000b" +
" slide.addShape(group);\r" + "slide.addShape(group);\u000b" +
" Graphics2D graphics = new PPGraphics2D(group);\r" + "Graphics2D graphics = new PPGraphics2D(group);\u000b" +
"\r" + "\u000b" +
" //draw a simple bar graph\r" + "//draw a simple bar graph\u000b" +
" int x = bounds.x + 50, y = bounds.y + 50;\r" + "int x = bounds.x + 50, y = bounds.y + 50;\u000b" +
" graphics.setFont(new Font(\"Arial\", Font.BOLD, 10));\r" + "graphics.setFont(new Font(\"Arial\", Font.BOLD, 10));\u000b" +
" for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {\r" + "for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {\u000b" +
" graphics.setColor(Color.black);\r" + " graphics.setColor(Color.black);\u000b" +
" int width = ((Integer)def[i+1]).intValue();\r" + " int width = ((Integer)def[i+1]).intValue();\u000b" +
" graphics.drawString(\"Q\" + idx, x-20, y+20);\r" + " graphics.drawString(\"Q\" + idx, x-20, y+20);\u000b" +
" graphics.drawString(width + \"%\", x + width + 10, y + 20);\r" + " graphics.drawString(width + \"%\", x + width + 10, y + 20);\u000b" +
" graphics.setColor((Color)def[i]);\r" + " graphics.setColor((Color)def[i]);\u000b" +
" graphics.fill(new Rectangle(x, y, width, 30));\r" + " graphics.fill(new Rectangle(x, y, width, 30));\u000b" +
" y += 40;\r" + " y += 40;\u000b" +
" }\r" + "}\u000b" +
" graphics.setColor(Color.black);\r" + "graphics.setColor(Color.black);\u000b" +
" graphics.setFont(new Font(\"Arial\", Font.BOLD, 14));\r" + "graphics.setFont(new Font(\"Arial\", Font.BOLD, 14));\u000b" +
" graphics.draw(bounds);\r" + "graphics.draw(bounds);\u000b" +
" graphics.drawString(\"Performance\", x + 70, y + 40);\r" + "graphics.drawString(\"Performance\", x + 70, y + 40);\u000b" +
"\r" + "\u000b" +
" FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\r" + "FileOutputStream out = new FileOutputStream(\"hslf-demo.ppt\");\u000b" +
" ppt.write(out);\r" + "ppt.write(out);\u000b" +
" out.close();"); "out.close();");
box3.setAnchor(new Rectangle(96, 110, 499, 378)); box3.setAnchor(new Rectangle(96, 110, 499, 378));
box3.setHorizontalCentered(true);
slide.addShape(box3); slide.addShape(box3);
} }
@ -435,38 +434,27 @@ public final class ApacheconEU08 {
slide.addShape(box1); slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox(); HSLFTextBox box2 = new HSLFTextBox();
box2.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32);
box2.setRunType(TextHeaderAtom.BODY_TYPE); box2.setRunType(TextHeaderAtom.BODY_TYPE);
box2.setText( box2.setText(
"Support for more PowerPoint functionality\r" + "Support for more PowerPoint functionality\r" +
"Rendering slides into java.awt.Graphics2D"); "Rendering slides into java.awt.Graphics2D\r" +
box2.setAnchor(new Rectangle(36, 126, 648, 100)); "A way to export slides into images or other formats\r" +
slide.addShape(box2); "Integration with Apache FOP - Formatting Objects Processor\r" +
HSLFTextBox box3 = new HSLFTextBox();
box3.getTextParagraphs().get(0).setIndentLevel(1);
box3.setRunType(TextHeaderAtom.BODY_TYPE);
box3.setText(
"A way to export slides into images or other formats");
box3.setAnchor(new Rectangle(36, 220, 648, 70));
slide.addShape(box3);
HSLFTextBox box4 = new HSLFTextBox();
box4.getTextParagraphs().get(0).getTextRuns().get(0).setFontSize(32);
box4.setRunType(TextHeaderAtom.BODY_TYPE);
box4.setText(
"Integration with Apache FOP - Formatting Objects Processor");
box4.setAnchor(new Rectangle(36, 290, 648, 90));
slide.addShape(box4);
HSLFTextBox box5 = new HSLFTextBox();
box5.getTextParagraphs().get(0).setIndentLevel(1);
box5.setRunType(TextHeaderAtom.BODY_TYPE);
box5.setText(
"Transformation of XSL-FO into PPT\r" + "Transformation of XSL-FO into PPT\r" +
"PPT2PDF transcoder"); "PPT2PDF transcoder"
box5.setAnchor(new Rectangle(36, 380, 648, 100)); );
slide.addShape(box5);
List<HSLFTextParagraph> tp = box2.getTextParagraphs();
for (int i : new byte[]{0,1,3}) {
tp.get(i).getTextRuns().get(0).setFontSize(28);
}
for (int i : new byte[]{2,4,5}) {
tp.get(i).getTextRuns().get(0).setFontSize(24);
tp.get(i).setIndentLevel(1);
}
box2.setAnchor(new Rectangle(36, 126, 648, 400));
slide.addShape(box2);
} }
public static void slide12(HSLFSlideShow ppt) throws IOException { public static void slide12(HSLFSlideShow ppt) throws IOException {

View File

@ -48,26 +48,42 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
} }
/** /**
* As we're purely mask based, just set flags for stuff * Calculate mask from the subPropMatches.
* that is set
*/ */
public int getWriteMask() { public int getWriteMask() {
return dataValue; /*
* The dataValue can't be taken as a mask, as sometimes certain properties
* are explicitly set to false, i.e. the mask says the property is defined
* but in the actually nibble the property is set to false
*/
int mask = 0, i = 0;
for (int subMask : subPropMasks) {
if (subPropMatches[i++]) mask |= subMask;
}
return mask;
}
public void setWriteMask(int containsField) {
int i = 0;
for (int subMask : subPropMasks) {
if ((containsField & subMask) != 0) subPropMatches[i] = true;
i++;
}
} }
/** /**
* Set the value of the text property, and recompute the sub * Set the value of the text property, and recompute the sub
* properties based on it * properties based on it, i.e. all unset subvalues won't be saved.
* Use {@link #setSubValue(boolean, int)} to explicitly set subvalues to {@code false}.
*/ */
@Override
public void setValue(int val) { public void setValue(int val) {
dataValue = val; dataValue = val;
// Figure out the values of the sub properties // Figure out the values of the sub properties
for(int i=0; i< subPropMatches.length; i++) { int i = 0;
subPropMatches[i] = false; for(int mask : subPropMasks) {
if((dataValue & subPropMasks[i]) != 0) { subPropMatches[i++] = ((val & mask) != 0);
subPropMatches[i] = true;
}
} }
} }
@ -75,16 +91,19 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
* Fetch the true/false status of the subproperty with the given index * Fetch the true/false status of the subproperty with the given index
*/ */
public boolean getSubValue(int idx) { public boolean getSubValue(int idx) {
return subPropMatches[idx]; return (dataValue & subPropMasks[idx]) != 0;
} }
/** /**
* Set the true/false status of the subproperty with the given index * Set the true/false status of the subproperty with the given index
*/ */
public void setSubValue(boolean value, int idx) { public void setSubValue(boolean value, int idx) {
if (subPropMatches[idx] == value) return; subPropMatches[idx] = true;
subPropMatches[idx] = value; if (value) {
dataValue ^= subPropMasks[idx]; dataValue |= subPropMasks[idx];
} else {
dataValue &= ~subPropMasks[idx];
}
} }
@Override @Override

View File

@ -34,20 +34,23 @@ public class CharFlagsTextProp extends BitMaskTextProp {
public static final String NAME = "char_flags"; public static final String NAME = "char_flags";
public CharFlagsTextProp() { public CharFlagsTextProp() {
super(2,0xffff, NAME, new String[] { super(2, 0xffff, NAME, new String[] {
"bold", // 0x0001 A bit that specifies whether the characters are bold. "bold", // 0x0001 A bit that specifies whether the characters are bold.
"italic", // 0x0002 A bit that specifies whether the characters are italicized. "italic", // 0x0002 A bit that specifies whether the characters are italicized.
"underline", // 0x0004 A bit that specifies whether the characters are underlined. "underline", // 0x0004 A bit that specifies whether the characters are underlined.
"char_unknown_1", // 0x0008 Undefined and MUST be ignored. "unused1", // 0x0008 Undefined and MUST be ignored.
"shadow", // 0x0010 A bit that specifies whether the characters have a shadow effect. "shadow", // 0x0010 A bit that specifies whether the characters have a shadow effect.
"fehint", // 0x0020 A bit that specifies whether characters originated from double-byte input. "fehint", // 0x0020 A bit that specifies whether characters originated from double-byte input.
"char_unknown_2", // 0x0040 Undefined and MUST be ignored. "unused2", // 0x0040 Undefined and MUST be ignored.
"kumi", // 0x0080 A bit that specifies whether Kumimoji are used for vertical text. "kumi", // 0x0080 A bit that specifies whether Kumimoji are used for vertical text.
"strikethrough", // 0x0100 Undefined and MUST be ignored. "strikethrough", // 0x0100 Undefined and MUST be ignored.
"emboss", // 0x0200 A bit that specifies whether the characters are embossed. "emboss", // 0x0200 A bit that specifies whether the characters are embossed.
"char_unknown_3", // 0x0400 Undefined and MUST be ignored. "pp9rt_1", // 0x0400 An unsigned integer that specifies the run grouping of additional text properties in StyleTextProp9Atom record.
"char_unknown_4", // 0x0800 Undefined and MUST be ignored. "pp9rt_2", // 0x0800
"char_unknown_5", // 0x1000 Undefined and MUST be ignored. "pp9rt_3", // 0x1000
"pp9rt_4", // 0x2000
"unused4_1", // 0x4000 Undefined and MUST be ignored.
"unused4_2", // 0x8000 Undefined and MUST be ignored.
} }
); );
} }

View File

@ -28,14 +28,127 @@ import org.apache.poi.util.LittleEndian;
* For a given run of characters, holds the properties (which could * For a given run of characters, holds the properties (which could
* be paragraph properties or character properties). * be paragraph properties or character properties).
* Used to hold the number of characters affected, the list of active * Used to hold the number of characters affected, the list of active
* properties, and the random reserved field 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 */
public static final TextProp[] paragraphTextPropTypes = {
// TextProp order is according to 2.9.20 TextPFException,
// bitmask order can be different
// new TextProp(0, 0x1, "hasBullet"),
// new TextProp(0, 0x2, "hasBulletFont"),
// new TextProp(0, 0x4, "hasBulletColor"),
// new TextProp(0, 0x8, "hasBulletSize"),
new ParagraphFlagsTextProp(),
new TextProp(2, 0x80, "bullet.char"),
new TextProp(2, 0x10, "bullet.font"),
new TextProp(2, 0x40, "bullet.size"),
new TextProp(4, 0x20, "bullet.color"),
new TextAlignmentProp(),
new TextProp(2, 0x1000, "linespacing"),
new TextProp(2, 0x2000, "spacebefore"),
new TextProp(2, 0x4000, "spaceafter"),
new TextProp(2, 0x100, "text.offset"), // left margin
// 0x200 - Undefined and MUST be ignored
new TextProp(2, 0x400, "bullet.offset"), // indent
new TextProp(2, 0x8000, "defaultTabSize"),
new TabStopPropCollection(), // tabstops size is variable!
new FontAlignmentProp(),
new TextProp(2, 0xE0000, "wrapFlags"), // charWrap | wordWrap | overflow
new TextProp(2, 0x200000, "textDirection"),
// 0x400000 MUST be zero and MUST be ignored
new TextProp(0, 0x800000, "bullet.blip"), // TODO: check size
new TextProp(0, 0x1000000, "bullet.scheme"), // TODO: check size
new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size
// 0xFC000000 MUST be zero and MUST be ignored
};
/** All the different kinds of character properties we might handle */
public static final TextProp[] characterTextPropTypes = new TextProp[] {
// new TextProp(0, 0x1, "bold"),
// new TextProp(0, 0x2, "italic"),
// new TextProp(0, 0x4, "underline"),
// new TextProp(0, 0x8, "unused1"),
// new TextProp(0, 0x10, "shadow"),
// new TextProp(0, 0x20, "fehint"),
// new TextProp(0, 0x40, "unused2"),
// new TextProp(0, 0x80, "kumi"),
// new TextProp(0, 0x100, "strikethrough"),
// new TextProp(0, 0x200, "emboss"),
// new TextProp(0, 0x400, "nibble1"),
// new TextProp(0, 0x800, "nibble2"),
// new TextProp(0, 0x1000, "nibble3"),
// new TextProp(0, 0x2000, "nibble4"),
// new TextProp(0, 0x4000, "unused4"),
// new TextProp(0, 0x8000, "unused5"),
new TextProp(0, 0x100000, "pp10ext"),
new TextProp(0, 0x1000000, "newAsian.font.index"), // A bit that specifies whether the newEAFontRef field of the TextCFException10 structure that contains this CFMasks exists.
new TextProp(0, 0x2000000, "cs.font.index"), // A bit that specifies whether the csFontRef field of the TextCFException10 structure that contains this CFMasks exists.
new TextProp(0, 0x4000000, "pp11ext"), // A bit that specifies whether the pp11ext field of the TextCFException10 structure that contains this CFMasks exists.
new CharFlagsTextProp(),
new TextProp(2, 0x10000, "font.index"),
new TextProp(2, 0x200000, "asian.font.index"),
new TextProp(2, 0x400000, "ansi.font.index"),
new TextProp(2, 0x800000, "symbol.font.index"),
new TextProp(2, 0x20000, "font.size"),
new TextProp(4, 0x40000, "font.color"),
new TextProp(2, 0x80000, "superscript")
};
public enum TextPropType {
paragraph, character;
}
private int charactersCovered; private int charactersCovered;
private short reservedField;
// indentLevel is only valid for paragraph collection
// if it's set to -1, it must be omitted - see 2.9.36 TextMasterStyleLevel
private short indentLevel = 0;
private final List<TextProp> textPropList = new ArrayList<TextProp>(); private final List<TextProp> textPropList = new ArrayList<TextProp>();
private int maskSpecial = 0; private int maskSpecial = 0;
private final TextProp[] potentialPropList; private final TextPropType textPropType;
/**
* Create a new collection of text properties (be they paragraph
* or character) which will be groked via a subsequent call to
* buildTextPropList().
*/
public TextPropCollection(int charactersCovered, TextPropType textPropType) {
this.charactersCovered = charactersCovered;
this.textPropType = textPropType;
}
public int getSpecialMask() { return maskSpecial; } public int getSpecialMask() { return maskSpecial; }
@ -61,7 +174,7 @@ public class TextPropCollection {
if (existing != null) return existing; if (existing != null) return existing;
TextProp base = null; TextProp base = null;
for (TextProp tp : potentialPropList) { for (TextProp tp : getPotentialProperties()) {
if (tp.getName().equals(name)) { if (tp.getName().equals(name)) {
base = tp; base = tp;
break; break;
@ -79,6 +192,10 @@ public class TextPropCollection {
return textProp; return textProp;
} }
private TextProp[] getPotentialProperties() {
return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes;
}
/** /**
* Add the property at the correct position. Replaces an existing property with the same name. * Add the property at the correct position. Replaces an existing property with the same name.
* *
@ -89,7 +206,7 @@ public class TextPropCollection {
int pos = 0; int pos = 0;
boolean found = false; boolean found = false;
for (TextProp curProp : potentialPropList) { for (TextProp curProp : getPotentialProperties()) {
String potName = curProp.getName(); String potName = curProp.getName();
if (pos == textPropList.size() || potName.equals(textProp.getName())) { if (pos == textPropList.size() || potName.equals(textProp.getName())) {
if (textPropList.size() > pos && potName.equals(textPropList.get(pos).getName())) { if (textPropList.size() > pos && potName.equals(textPropList.get(pos).getName())) {
@ -123,7 +240,7 @@ public class TextPropCollection {
// For each possible entry, see if we match the mask // For each possible entry, see if we match the mask
// If we do, decode that, save it, and shuffle on // If we do, decode that, save it, and shuffle on
for(TextProp tp : potentialPropList) { for(TextProp tp : getPotentialProperties()) {
// Check there's still data left to read // Check there's still data left to read
// Check if this property is found in the mask // Check if this property is found in the mask
@ -150,6 +267,9 @@ public class TextPropCollection {
continue; continue;
} }
prop.setValue(val); prop.setValue(val);
if (prop instanceof BitMaskTextProp) {
((BitMaskTextProp)prop).setWriteMask(containsField);
}
bytesPassed += prop.getSize(); bytesPassed += prop.getSize();
addProp(prop); addProp(prop);
} }
@ -159,31 +279,12 @@ public class TextPropCollection {
return bytesPassed; return bytesPassed;
} }
/**
* Create a new collection of text properties (be they paragraph
* or character) which will be groked via a subsequent call to
* buildTextPropList().
*/
public TextPropCollection(int charactersCovered, short reservedField, TextProp[] potentialPropList) {
this.charactersCovered = charactersCovered;
this.reservedField = reservedField;
this.potentialPropList = potentialPropList;
}
/**
* Create a new collection of text properties (be they paragraph
* or character) for a run of text without any
*/
public TextPropCollection(int textSize, TextProp[] potentialPropList) {
this(textSize, (short)-1, potentialPropList);
}
/** /**
* Clones the given text properties * Clones the given text properties
*/ */
public void copy(TextPropCollection other) { public void copy(TextPropCollection other) {
this.charactersCovered = other.charactersCovered; this.charactersCovered = other.charactersCovered;
this.reservedField = other.reservedField; this.indentLevel = other.indentLevel;
this.maskSpecial = other.maskSpecial; this.maskSpecial = other.maskSpecial;
this.textPropList.clear(); this.textPropList.clear();
for (TextProp tp : other.textPropList) { for (TextProp tp : other.textPropList) {
@ -209,17 +310,17 @@ public class TextPropCollection {
// First goes the number of characters we affect // First goes the number of characters we affect
StyleTextPropAtom.writeLittleEndian(charactersCovered,o); StyleTextPropAtom.writeLittleEndian(charactersCovered,o);
// Then we have the reserved field if required // Then we have the indentLevel field if it's a paragraph collection
if(reservedField > -1) { if (textPropType == TextPropType.paragraph && indentLevel > -1) {
StyleTextPropAtom.writeLittleEndian(reservedField,o); StyleTextPropAtom.writeLittleEndian(indentLevel, o);
} }
// Then the mask field // Then the mask field
int mask = maskSpecial; int mask = maskSpecial;
for(TextProp textProp : textPropList) { for (TextProp textProp : textPropList) {
//sometimes header indicates that the bitmask is present but its value is 0 // sometimes header indicates that the bitmask is present but its value is 0
if (textProp instanceof BitMaskTextProp) { if (textProp instanceof BitMaskTextProp) {
if(mask == 0) mask |= textProp.getWriteMask(); if (mask == 0) mask |= textProp.getWriteMask();
} }
else { else {
mask |= textProp.getWriteMask(); mask |= textProp.getWriteMask();
@ -228,17 +329,12 @@ public class TextPropCollection {
StyleTextPropAtom.writeLittleEndian(mask,o); StyleTextPropAtom.writeLittleEndian(mask,o);
// Then the contents of all the properties // Then the contents of all the properties
for (TextProp potProp : potentialPropList) { for (TextProp potProp : getPotentialProperties()) {
for(TextProp textProp : textPropList) { for(TextProp textProp : textPropList) {
if (!textProp.getName().equals(potProp.getName())) continue; if (!textProp.getName().equals(potProp.getName())) continue;
int val = textProp.getValue(); int val = textProp.getValue();
if (textProp instanceof BitMaskTextProp && val == 0 if (textProp instanceof BitMaskTextProp && textProp.getWriteMask() == 0) {
&& !(textProp instanceof ParagraphFlagsTextProp)
// && !(textProp instanceof CharFlagsTextProp)
) {
// don't add empty properties, as they can't be recognized while reading // don't add empty properties, as they can't be recognized while reading
// strangely this doesn't apply for ParagraphFlagsTextProp in contrast
// to the documentation in 2.9.20 TextPFException
continue; continue;
} else if (textProp.getSize() == 2) { } else if (textProp.getSize() == 2) {
StyleTextPropAtom.writeLittleEndian((short)val,o); StyleTextPropAtom.writeLittleEndian((short)val,o);
@ -249,12 +345,15 @@ public class TextPropCollection {
} }
} }
public short getReservedField(){ public short getIndentLevel(){
return reservedField; return indentLevel;
} }
public void setReservedField(short val){ public void setIndentLevel(short indentLevel) {
reservedField = val; if (textPropType == TextPropType.character) {
throw new RuntimeException("trying to set an indent on a character collection.");
}
this.indentLevel = indentLevel;
} }
public int hashCode() { public int hashCode() {
@ -262,7 +361,7 @@ public class TextPropCollection {
int result = 1; int result = 1;
result = prime * result + charactersCovered; result = prime * result + charactersCovered;
result = prime * result + maskSpecial; result = prime * result + maskSpecial;
result = prime * result + reservedField; result = prime * result + indentLevel;
result = prime * result + ((textPropList == null) ? 0 : textPropList.hashCode()); result = prime * result + ((textPropList == null) ? 0 : textPropList.hashCode());
return result; return result;
} }
@ -275,7 +374,7 @@ public class TextPropCollection {
if (getClass() != other.getClass()) return false; if (getClass() != other.getClass()) return false;
TextPropCollection o = (TextPropCollection)other; TextPropCollection o = (TextPropCollection)other;
if (o.maskSpecial != this.maskSpecial || o.reservedField != this.reservedField) { if (o.maskSpecial != this.maskSpecial || o.indentLevel != this.indentLevel) {
return false; return false;
} }
@ -303,6 +402,16 @@ public class TextPropCollection {
for(TextProp p : getTextPropList()) { for(TextProp p : getTextPropList()) {
out.append(" " + p.getName() + " = " + p.getValue() ); out.append(" " + p.getName() + " = " + p.getValue() );
out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n"); out.append(" (0x" + HexDump.toHex(p.getValue()) + ")\n");
if (p instanceof BitMaskTextProp) {
BitMaskTextProp bm = (BitMaskTextProp)p;
int i = 0;
for (String s : bm.getSubPropNames()) {
if (bm.getSubPropMatches()[i]) {
out.append(" " + s + " = " + bm.getSubValue(i) + "\n");
}
i++;
}
}
} }
out.append(" bytes that would be written: \n"); out.append(" bytes that would be written: \n");

View File

@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.poi.hslf.model.textproperties.*; import org.apache.poi.hslf.model.textproperties.*;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.util.*; import org.apache.poi.util.*;
/** /**
@ -110,66 +111,6 @@ public final class StyleTextPropAtom extends RecordAtom
return length; return length;
} }
/** All the different kinds of paragraph properties we might handle */
public static final TextProp[] paragraphTextPropTypes = {
// TextProp order is according to 2.9.20 TextPFException,
// bitmask order can be different
new TextProp(0, 0x1, "hasBullet"),
new TextProp(0, 0x2, "hasBulletFont"),
new TextProp(0, 0x4, "hasBulletColor"),
new TextProp(0, 0x8, "hasBulletSize"),
new ParagraphFlagsTextProp(),
new TextProp(2, 0x80, "bullet.char"),
new TextProp(2, 0x10, "bullet.font"),
new TextProp(2, 0x40, "bullet.size"),
new TextProp(4, 0x20, "bullet.color"),
new TextAlignmentProp(),
new TextProp(2, 0x1000, "linespacing"),
new TextProp(2, 0x2000, "spacebefore"),
new TextProp(2, 0x4000, "spaceafter"),
new TextProp(2, 0x100, "text.offset"), // left margin
// 0x200 - Undefined and MUST be ignored
new TextProp(2, 0x400, "bullet.offset"), // indent
new TextProp(2, 0x8000, "defaultTabSize"),
new TabStopPropCollection(), // tabstops size is variable!
new FontAlignmentProp(),
new TextProp(2, 0xE0000, "wrapFlags"), // charWrap | wordWrap | overflow
new TextProp(2, 0x200000, "textDirection"),
// 0x400000 MUST be zero and MUST be ignored
new TextProp(0, 0x800000, "bullet.blip"), // TODO: check size
new TextProp(0, 0x1000000, "bullet.scheme"), // TODO: check size
new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size
// 0xFC000000 MUST be zero and MUST be ignored
};
/** All the different kinds of character properties we might handle */
public static final TextProp[] characterTextPropTypes = new TextProp[] {
new TextProp(0, 0x1, "bold"),
new TextProp(0, 0x2, "italic"),
new TextProp(0, 0x4, "underline"),
new TextProp(0, 0x8, "unused1"),
new TextProp(0, 0x10, "shadow"),
new TextProp(0, 0x20, "fehint"),
new TextProp(0, 0x40, "unused2"),
new TextProp(0, 0x80, "kumi"),
new TextProp(0, 0x100, "unused3"),
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 CharFlagsTextProp(),
new TextProp(2, 0x10000, "font.index"),
new TextProp(0, 0x100000, "pp10ext"),
new TextProp(2, 0x200000, "asian.font.index"),
new TextProp(2, 0x400000, "ansi.font.index"),
new TextProp(2, 0x800000, "symbol.font.index"),
new TextProp(2, 0x20000, "font.size"),
new TextProp(4, 0x40000, "font.color"),
new TextProp(2, 0x80000, "superscript")
};
/* *************** record code follows ********************** */ /* *************** record code follows ********************** */
/** /**
@ -217,15 +158,8 @@ public final class StyleTextPropAtom extends RecordAtom
paragraphStyles = new ArrayList<TextPropCollection>(); paragraphStyles = new ArrayList<TextPropCollection>();
charStyles = new ArrayList<TextPropCollection>(); charStyles = new ArrayList<TextPropCollection>();
TextPropCollection defaultParagraphTextProps = addParagraphTextPropCollection(parentTextSize);
new TextPropCollection(parentTextSize, (short)0, paragraphTextPropTypes); addCharacterTextPropCollection(parentTextSize);
defaultParagraphTextProps.addWithName("paragraph_flags");
paragraphStyles.add(defaultParagraphTextProps);
TextPropCollection defaultCharacterTextProps =
new TextPropCollection(parentTextSize, characterTextPropTypes);
defaultCharacterTextProps.addWithName("char_flags");
charStyles.add(defaultCharacterTextProps);
// Set us as now initialised // Set us as now initialised
initialised = true; initialised = true;
@ -269,7 +203,7 @@ public final class StyleTextPropAtom extends RecordAtom
* contains, so we can go ahead and initialise ourselves. * contains, so we can go ahead and initialise ourselves.
*/ */
public void setParentTextSize(int size) { public void setParentTextSize(int size) {
// if (initialised) return; if (initialised) return;
int pos = 0; int pos = 0;
int textHandled = 0; int textHandled = 0;
@ -295,7 +229,8 @@ public final class StyleTextPropAtom extends RecordAtom
pos += 4; pos += 4;
// Now make sense of those properties // Now make sense of those properties
TextPropCollection thisCollection = new TextPropCollection(textLen, indent, paragraphTextPropTypes); TextPropCollection thisCollection = new TextPropCollection(textLen, TextPropType.paragraph);
thisCollection.setIndentLevel(indent);
int plSize = thisCollection.buildTextPropList(paraFlags, rawContents, pos); int plSize = thisCollection.buildTextPropList(paraFlags, rawContents, pos);
pos += plSize; pos += plSize;
@ -322,16 +257,13 @@ public final class StyleTextPropAtom extends RecordAtom
textHandled += textLen; textHandled += textLen;
pos += 4; pos += 4;
// There is no 2 byte value
short no_val = -1;
// Grab the 4 byte value that tells us what properties follow // Grab the 4 byte value that tells us what properties follow
int charFlags = LittleEndian.getInt(rawContents,pos); int charFlags = LittleEndian.getInt(rawContents,pos);
pos += 4; pos += 4;
// Now make sense of those properties // Now make sense of those properties
// (Assuming we actually have some) // (Assuming we actually have some)
TextPropCollection thisCollection = new TextPropCollection(textLen, no_val, characterTextPropTypes); TextPropCollection thisCollection = new TextPropCollection(textLen, TextPropType.character);
int chSize = thisCollection.buildTextPropList(charFlags, rawContents, pos); int chSize = thisCollection.buildTextPropList(charFlags, rawContents, pos);
pos += chSize; pos += chSize;
@ -386,7 +318,7 @@ public final class StyleTextPropAtom extends RecordAtom
// Now, we do the character ones // Now, we do the character ones
for(TextPropCollection tpc : charStyles) { for(TextPropCollection tpc : charStyles) {
// ditto for the char flags // ditto for the char flags
tpc.addWithName(CharFlagsTextProp.NAME); // tpc.addWithName(CharFlagsTextProp.NAME);
tpc.writeOut(baos); tpc.writeOut(baos);
} }
@ -414,7 +346,7 @@ public final class StyleTextPropAtom extends RecordAtom
* @return the new TextPropCollection, which will then be in the list * @return the new TextPropCollection, which will then be in the list
*/ */
public TextPropCollection addParagraphTextPropCollection(int charactersCovered) { public TextPropCollection addParagraphTextPropCollection(int charactersCovered) {
TextPropCollection tpc = new TextPropCollection(charactersCovered, (short)0, paragraphTextPropTypes); TextPropCollection tpc = new TextPropCollection(charactersCovered, TextPropType.paragraph);
paragraphStyles.add(tpc); paragraphStyles.add(tpc);
return tpc; return tpc;
} }
@ -424,7 +356,7 @@ public final class StyleTextPropAtom extends RecordAtom
* @return the new TextPropCollection, which will then be in the list * @return the new TextPropCollection, which will then be in the list
*/ */
public TextPropCollection addCharacterTextPropCollection(int charactersCovered) { public TextPropCollection addCharacterTextPropCollection(int charactersCovered) {
TextPropCollection tpc = new TextPropCollection(charactersCovered, characterTextPropTypes); TextPropCollection tpc = new TextPropCollection(charactersCovered, TextPropType.character);
charStyles.add(tpc); charStyles.add(tpc);
return tpc; return tpc;
} }

View File

@ -19,11 +19,11 @@ package org.apache.poi.hslf.record;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
import org.apache.poi.hslf.model.textproperties.ParagraphFlagsTextProp;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection; import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
/** /**
@ -48,43 +48,12 @@ public final class TxMasterStyleAtom extends RecordAtom {
*/ */
public static final int MAX_INDENT = 5; public static final int MAX_INDENT = 5;
/*
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")
};
*/
private byte[] _header; private byte[] _header;
private static long _type = 4003; private static long _type = 4003;
private byte[] _data; private byte[] _data;
private TextPropCollection[] prstyles; private List<TextPropCollection> paragraphStyles;
private TextPropCollection[] chstyles; private List<TextPropCollection> charStylesyles;
protected TxMasterStyleAtom(byte[] source, int start, int len) { protected TxMasterStyleAtom(byte[] source, int start, int len) {
_header = new byte[8]; _header = new byte[8];
@ -129,8 +98,8 @@ public final class TxMasterStyleAtom extends RecordAtom {
* *
* @return character styles defined in this record * @return character styles defined in this record
*/ */
public TextPropCollection[] getCharacterStyles(){ public List<TextPropCollection> getCharacterStyles(){
return chstyles; return charStylesyles;
} }
/** /**
@ -138,8 +107,8 @@ public final class TxMasterStyleAtom extends RecordAtom {
* *
* @return paragraph styles defined in this record * @return paragraph styles defined in this record
*/ */
public TextPropCollection[] getParagraphStyles(){ public List<TextPropCollection> getParagraphStyles(){
return prstyles; return paragraphStyles;
} }
/** /**
@ -157,7 +126,6 @@ public final class TxMasterStyleAtom extends RecordAtom {
/** /**
* parse the record data and initialize styles * parse the record data and initialize styles
*/ */
@SuppressWarnings("unused")
protected void init(){ protected void init(){
//type of the text //type of the text
int type = getTextType(); int type = getTextType();
@ -169,28 +137,31 @@ public final class TxMasterStyleAtom extends RecordAtom {
short levels = LittleEndian.getShort(_data, 0); short levels = LittleEndian.getShort(_data, 0);
pos += LittleEndian.SHORT_SIZE; pos += LittleEndian.SHORT_SIZE;
prstyles = new TextPropCollection[levels]; paragraphStyles = new ArrayList<TextPropCollection>(levels);
chstyles = new TextPropCollection[levels]; charStylesyles = new ArrayList<TextPropCollection>(levels);
for(short j = 0; j < levels; j++) { for(short j = 0; j < levels; j++) {
TextPropCollection prprops = new TextPropCollection(0, TextPropType.paragraph); // getParagraphProps(type, j)
if (type >= TextHeaderAtom.CENTRE_BODY_TYPE) { if (type >= TextHeaderAtom.CENTRE_BODY_TYPE) {
// Fetch the 2 byte value, that is safe to ignore for some types of text // Fetch the 2 byte value, that is safe to ignore for some types of text
short val = LittleEndian.getShort(_data, pos); short indentLevel = LittleEndian.getShort(_data, pos);
prprops.setIndentLevel(indentLevel);
pos += LittleEndian.SHORT_SIZE; pos += LittleEndian.SHORT_SIZE;
} else {
prprops.setIndentLevel((short)-1);
} }
head = LittleEndian.getInt(_data, pos); head = LittleEndian.getInt(_data, pos);
pos += LittleEndian.INT_SIZE; pos += LittleEndian.INT_SIZE;
TextPropCollection prprops = new TextPropCollection(0, getParagraphProps(type, j));
pos += prprops.buildTextPropList( head, _data, pos); pos += prprops.buildTextPropList( head, _data, pos);
prstyles[j] = prprops; paragraphStyles.add(prprops);
head = LittleEndian.getInt(_data, pos); head = LittleEndian.getInt(_data, pos);
pos += LittleEndian.INT_SIZE; pos += LittleEndian.INT_SIZE;
TextPropCollection chprops = new TextPropCollection(0, getCharacterProps(type, j)); TextPropCollection chprops = new TextPropCollection(0, TextPropType.character); // getCharacterProps(type, j)
pos += chprops.buildTextPropList( head, _data, pos); pos += chprops.buildTextPropList( head, _data, pos);
chstyles[j] = chprops; charStylesyles.add(chprops);
} }
} }
@ -201,12 +172,12 @@ public final class TxMasterStyleAtom extends RecordAtom {
* Depending on the level and type, it may be our special * Depending on the level and type, it may be our special
* ones, or the standard StyleTextPropAtom ones * ones, or the standard StyleTextPropAtom ones
*/ */
protected TextProp[] getParagraphProps(int type, int level){ // protected TextProp[] getParagraphProps(int type, int level){
return StyleTextPropAtom.paragraphTextPropTypes; // return StyleTextPropAtom.paragraphTextPropTypes;
// return (level != 0 || type >= MAX_INDENT) // return (level != 0 || type >= MAX_INDENT)
// ? StyleTextPropAtom.paragraphTextPropTypes // ? StyleTextPropAtom.paragraphTextPropTypes
// : paragraphSpecialPropTypes; // : paragraphSpecialPropTypes;
} // }
/** /**
* Character properties for the specified text type and * Character properties for the specified text type and
@ -214,10 +185,10 @@ public final class TxMasterStyleAtom extends RecordAtom {
* Depending on the level and type, it may be our special * Depending on the level and type, it may be our special
* ones, or the standard StyleTextPropAtom ones * ones, or the standard StyleTextPropAtom ones
*/ */
protected TextProp[] getCharacterProps(int type, int level){ // protected TextProp[] getCharacterProps(int type, int level){
return StyleTextPropAtom.characterTextPropTypes; // return StyleTextPropAtom.characterTextPropTypes;
// return (level != 0 || type >= MAX_INDENT) // return (level != 0 || type >= MAX_INDENT)
// ? StyleTextPropAtom.characterTextPropTypes // ? StyleTextPropAtom.characterTextPropTypes
// : characterSpecialPropTypes; // : characterSpecialPropTypes;
} // }
} }

View File

@ -76,9 +76,9 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
TextProp prop = null; TextProp prop = null;
for (int i = level; i >= 0; i--) { for (int i = level; i >= 0; i--) {
TextPropCollection[] styles = List<TextPropCollection> styles =
isCharacter ? _txmaster[txtype].getCharacterStyles() : _txmaster[txtype].getParagraphStyles(); isCharacter ? _txmaster[txtype].getCharacterStyles() : _txmaster[txtype].getParagraphStyles();
if (i < styles.length) prop = styles[i].findByName(name); if (i < styles.size()) prop = styles.get(i).findByName(name);
if (prop != null) break; if (prop != null) break;
} }
if (prop == null) { if (prop == null) {

View File

@ -18,12 +18,11 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import java.awt.Color; import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*; import java.util.*;
import org.apache.poi.hslf.model.PPFont; import org.apache.poi.hslf.model.PPFont;
import org.apache.poi.hslf.model.textproperties.*; import org.apache.poi.hslf.model.textproperties.*;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.hslf.record.*; import org.apache.poi.hslf.record.*;
import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.util.*; import org.apache.poi.util.*;
@ -54,7 +53,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
private TextBytesAtom _byteAtom; private TextBytesAtom _byteAtom;
private TextCharsAtom _charAtom; private TextCharsAtom _charAtom;
private StyleTextPropAtom _styleAtom; private StyleTextPropAtom _styleAtom;
private TextPropCollection _paragraphStyle = new TextPropCollection(1, StyleTextPropAtom.paragraphTextPropTypes); private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
protected TextRulerAtom _ruler; protected TextRulerAtom _ruler;
protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>(); protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();
@ -407,7 +406,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
* @return indentation level * @return indentation level
*/ */
public int getIndentLevel() { public int getIndentLevel() {
return _paragraphStyle == null ? 0 : _paragraphStyle.getReservedField(); return _paragraphStyle == null ? 0 : _paragraphStyle.getIndentLevel();
} }
/** /**
@ -416,7 +415,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
* @param level indentation level. Must be in the range [0, 4] * @param level indentation level. Must be in the range [0, 4]
*/ */
public void setIndentLevel(int level) { public void setIndentLevel(int level) {
if( _paragraphStyle != null ) _paragraphStyle.setReservedField((short)level); if( _paragraphStyle != null ) _paragraphStyle.setIndentLevel((short)level);
} }
/** /**
@ -591,11 +590,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
*/ */
protected static TextProp fetchOrAddTextProp(TextPropCollection textPropCol, String textPropName) { protected static TextProp fetchOrAddTextProp(TextPropCollection textPropCol, String textPropName) {
// Fetch / Add the TextProp // Fetch / Add the TextProp
TextProp tp = textPropCol.findByName(textPropName); return textPropCol.addWithName(textPropName);
if (tp == null) {
tp = textPropCol.addWithName(textPropName);
}
return tp;
} }
protected boolean getFlag(int index) { protected boolean getFlag(int index) {
@ -621,7 +616,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
protected void setFlag(int index, boolean value) { protected void setFlag(int index, boolean value) {
// Ensure we have the StyleTextProp atom we're going to need // Ensure we have the StyleTextProp atom we're going to need
if(_paragraphStyle == null) { if(_paragraphStyle == null) {
_paragraphStyle = new TextPropCollection(1, StyleTextPropAtom.paragraphTextPropTypes); _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
} }
BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME); BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME);
@ -747,9 +742,11 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
for (HSLFTextParagraph p : paragraphs) { for (HSLFTextParagraph p : paragraphs) {
if (newRecord == byteAtom) { if (newRecord == byteAtom) {
p._byteAtom = byteAtom;
p._charAtom = null; p._charAtom = null;
} else { } else {
p._byteAtom = null; p._byteAtom = null;
p._charAtom = charAtom;
} }
} }
@ -825,8 +822,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
htp.setShapeId(prevHtp.getShapeId()); htp.setShapeId(prevHtp.getShapeId());
htp.supplySheet(prevHtp.getSheet()); htp.supplySheet(prevHtp.getSheet());
paragraphs.add(htp); paragraphs.add(htp);
isFirst = false;
} }
isFirst = false;
TextPropCollection tpc = htr.getCharacterStyle(); TextPropCollection tpc = htr.getCharacterStyle();
// special case, last text run is empty, we will reuse it // special case, last text run is empty, we will reuse it
@ -1083,7 +1080,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
ccRun += ccStyle-ccRun; ccRun += ccStyle-ccRun;
} }
TextPropCollection pCopy = new TextPropCollection(0, StyleTextPropAtom.characterTextPropTypes); TextPropCollection pCopy = new TextPropCollection(0, TextPropType.character);
pCopy.copy(p); pCopy.copy(p);
trun.setCharacterStyle(pCopy); trun.setCharacterStyle(pCopy);
@ -1117,7 +1114,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) { for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) {
if (paraIdx >= paragraphs.size() || ccPara >= ccStyle-1) return; if (paraIdx >= paragraphs.size() || ccPara >= ccStyle-1) return;
HSLFTextParagraph htp = paragraphs.get(paraIdx); HSLFTextParagraph htp = paragraphs.get(paraIdx);
TextPropCollection pCopy = new TextPropCollection(0, StyleTextPropAtom.paragraphTextPropTypes); TextPropCollection pCopy = new TextPropCollection(0, TextPropType.paragraph);
pCopy.copy(p); pCopy.copy(p);
htp.setParagraphStyle(pCopy); htp.setParagraphStyle(pCopy);
int len = 0; int len = 0;
@ -1165,16 +1162,16 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta); HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta);
htp.setParagraphStyle(paraStyle); htp.setParagraphStyle(paraStyle);
htp._records = new Record[0]; htp._records = new Record[0];
htp.setBullet(false); // htp.setBullet(false);
htp.setLineSpacing(100); // htp.setLineSpacing(100);
htp.setLeftMargin(0); // htp.setLeftMargin(0);
htp.setIndent(0); // htp.setIndent(0);
// set wrap flags // set wrap flags
HSLFTextRun htr = new HSLFTextRun(htp); HSLFTextRun htr = new HSLFTextRun(htp);
htr.setCharacterStyle(charStyle); htr.setCharacterStyle(charStyle);
htr.setText("\r"); htr.setText("\r");
htr.setFontColor(Color.black); // htr.setFontColor(Color.black);
htp.addTextRun(htr); htp.addTextRun(htr);
return Arrays.asList(htp); return Arrays.asList(htp);

View File

@ -22,8 +22,8 @@ import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.fetchOrAddTextProp
import java.awt.Color; import java.awt.Color;
import org.apache.poi.hslf.model.textproperties.*; import org.apache.poi.hslf.model.textproperties.*;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.hslf.record.ColorSchemeAtom; import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.StyleTextPropAtom;
import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -45,7 +45,7 @@ public final class HSLFTextRun implements TextRun {
* Our paragraph and character style. * Our paragraph and character style.
* Note - we may share these styles with other RichTextRuns * Note - we may share these styles with other RichTextRuns
*/ */
private TextPropCollection characterStyle = new TextPropCollection(0, StyleTextPropAtom.characterTextPropTypes); private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character);
/** /**
* Create a new wrapper around a rich text string * Create a new wrapper around a rich text string
@ -60,6 +60,7 @@ public final class HSLFTextRun implements TextRun {
} }
public void setCharacterStyle(TextPropCollection characterStyle) { public void setCharacterStyle(TextPropCollection characterStyle) {
assert(characterStyle != null);
this.characterStyle = characterStyle; this.characterStyle = characterStyle;
} }
@ -162,12 +163,6 @@ 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) {
// Ensure we have the StyleTextProp atom we're going to need
if(characterStyle == null) {
characterStyle = new TextPropCollection(1, StyleTextPropAtom.characterTextPropTypes);
// characterStyle will now be defined
}
TextProp tp = fetchOrAddTextProp(characterStyle, propName); TextProp tp = fetchOrAddTextProp(characterStyle, propName);
tp.setValue(val); tp.setValue(val);
} }
@ -375,11 +370,6 @@ public final class HSLFTextRun implements TextRun {
} }
protected void setFlag(int index, boolean value) { protected void setFlag(int index, boolean value) {
// Ensure we have the StyleTextProp atom we're going to need
if (characterStyle == null) {
characterStyle = new TextPropCollection(1, StyleTextPropAtom.characterTextPropTypes);
}
BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(characterStyle, CharFlagsTextProp.NAME); BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(characterStyle, CharFlagsTextProp.NAME);
prop.setSubValue(value, index); prop.setSubValue(value, index);
} }